假设我有以下pandas DataFrame:
df = pd.DataFrame({
'team': ['Warriors', 'Warriors', 'Warriors', 'Rockets', 'Rockets'],
'player': ['Stephen Curry', 'Klay Thompson', 'Kevin Durant', 'Chris Paul', 'James Harden']})
当我尝试对team
列进行分组并执行操作时,我得到SettingWithCopyWarning
:
for team, team_df in df.groupby(by='team'):
# team_df = team_df.copy() # produces no warning
team_df['rank'] = 10 # produces warning
team_df.loc[:, 'rank'] = 10 # produces warning
SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_index,col_indexer] = value instead
df_team['rank'] = 10
如果我取消注释生成子DataFrame副本的行,我不会收到错误。这通常是避免这种警告的最佳做法,还是我做错了什么?
注意我不想编辑原始DataFrame df
。此外,我知道这个示例可以更好地完成,但我的用例要复杂得多,需要对原始DataFrame进行分组,并根据不同的DataFrame和该唯一组的规范执行一系列操作。
答案 0 :(得分:6)
一旦你找到this article并且是
自信你知道如何避免链式索引(通过使用.loc
或
iloc
)然后您可以关闭SettingWithCopyWarning
pd.options.mode.chained_assignment = None
再也不会被这个警告所困扰。
自从你写了
注意我不想编辑原始DataFrame df
并且您正在使用.loc
分配给team_df
,很明显您
已经知道修改副本(team_df
)不会修改原件
(df
),因此此处发出的SettingWithCopyWarning
只会令人讨厌。
SettingWithCopyWarning
出现在你所处的各种情况中
正确编码,即使使用.loc
或.iloc
也是如此。没有“正确”的编码方式
这有助于避免触发SettingWithCopyWarning
s。
因此,我只想用
全局关闭此警告pd.options.mode.chained_assignment = None
我通常不建议仅使用team_df = team_df.copy()
来避免
SettingWithCopyWarning
s - 复制数据帧可能会耗尽
特别是当数据帧很大或者在循环中多次完成时,性能。
如果您想turn off the warning in just one location,可以使用
team_df.is_copy = False
它有同样的目的,但不会造成性能损失。但请注意,
官方Pandas API中未提及is_copy
,因此可能不会
保证在将来的所有版本中都存在或对此有用
大熊猫。因此,如果稳健性是一个优先事项,但性能不是那么可能使用
team_df = team_df.copy()
。但我觉得有经验的方法更健全
Pandas程序员要么全局关闭警告,要么 - 如果你
想要非常小心 - 保留警告,手动检查,但接受
它有时会被正确的代码触发。
答案 1 :(得分:0)
pandas split apply combine docs并不是很好。这应该指向正确的方向
def apply_fun(team_df):
team_df['rank'] = 10
return team_df
df.groupby('team').apply(apply_fun)
df['column_rank'] = df.groupby('team')['column'].transform(lambda x: x.rank())