创建依赖其他列的新列时遇str属性错误,求解决方案
问题解决:'str' object has no attribute 'str' 错误及投篮命中率计算优化
错误原因
你在循环中用df_curry.iloc[row]["Golden State"]取出的是单个字符串值,而.str.contains()是pandas Series(列对象)的专属方法,单个字符串没有这个属性,因此触发报错。
解决方法
方法1:修改循环逻辑,使用原生字符串匹配
保留循环思路,改用Python原生的正则匹配替代str.contains(),同时处理SettingWithCopyWarning问题:
import pandas as pd import re # 原数据加载逻辑不变 url = 'https://www.basketball-reference.com/boxscores/pbp/200911060GSW.html' dfs = pd.read_html(url) df = dfs[0] df.columns = df.columns.droplevel() df.rename(columns={'Unnamed: 2_level_1': 'PM1', 'Unnamed: 4_level_1': 'PM2'}, inplace=True) # 筛选Curry数据并复制,避免修改原数据切片引发警告 df_curry = df.loc[df["Golden State"].str.contains("Curry", na=False)].copy() # 初始化统计列 df_curry["Field Goals Hit"] = 0 df_curry["Field Goals Missed"] = 0 df_curry["Field Goals Percentage"] = 0 field_throws_missed = 0 field_throws_hit = 0 # 改用iterrows遍历行,用原生正则匹配动作描述 for idx, row in df_curry.iterrows(): action = row["Golden State"] if re.search(r'misses 2|misses 3', action): field_throws_missed += 1 df_curry.loc[idx, "Field Goals Missed"] = field_throws_missed elif re.search(r'makes 2|makes 3', action): field_throws_hit += 1 df_curry.loc[idx, "Field Goals Hit"] = field_throws_hit # 计算最终命中率 total_attempts = field_throws_hit + field_throws_missed if total_attempts > 0: df_curry["Field Goals Percentage"] = (field_throws_hit / total_attempts).round(3)
方法2:抛弃循环,使用pandas向量化操作(推荐)
这是更符合pandas设计思想的写法,执行效率更高,代码更简洁:
import pandas as pd # 原数据加载逻辑不变 url = 'https://www.basketball-reference.com/boxscores/pbp/200911060GSW.html' dfs = pd.read_html(url) df = dfs[0] df.columns = df.columns.droplevel() df.rename(columns={'Unnamed: 2_level_1': 'PM1', 'Unnamed: 4_level_1': 'PM2'}, inplace=True) # 筛选Curry数据并复制 df_curry = df.loc[df["Golden State"].str.contains("Curry", na=False)].copy() # 标记命中/未命中的行 df_curry['is_hit'] = df_curry["Golden State"].str.contains(r'makes 2|makes 3', na=False) df_curry['is_miss'] = df_curry["Golden State"].str.contains(r'misses 2|misses 3', na=False) # 计算累计命中/未命中数 df_curry["Field Goals Hit"] = df_curry['is_hit'].cumsum() df_curry["Field Goals Missed"] = df_curry['is_miss'].cumsum() # 计算累计命中率,处理未产生投篮的除零情况 total_attempts = df_curry["Field Goals Hit"] + df_curry["Field Goals Missed"] df_curry["Field Goals Percentage"] = (df_curry["Field Goals Hit"] / total_attempts).fillna(0).round(3) # 可选:删除临时标记列 df_curry.drop(['is_hit', 'is_miss'], axis=1, inplace=True)
关键要点
- 处理警告:对筛选后的
df_curry调用.copy(),避免修改原数据切片引发SettingWithCopyWarning。 - 向量化优势:避免循环遍历,利用pandas内置的向量化方法,数据量越大,执行效率提升越明显。
- 命中率计算:用
cumsum()生成累计命中/未命中数,通过除法计算实时累计命中率,fillna(0)处理还未产生投篮的初始状态。
内容的提问来源于stack exchange,提问作者nick.s99
相关产品推荐
相关产品推荐

