提问人:Bogdan Doicin 提问时间:4/6/2023 更新时间:4/6/2023 访问量:581
如何修复 pandas 中的“尝试在 DataFrame 中的切片副本上设置值”警告?
How can I fix the "A value is trying to be set on a copy of a slice from a DataFrame" warning in pandas?
问:
我有以下Python函数:
def compute_average_fg_rating(df, mask=''):
df = df[['HorseId', 'FGrating']]
if len(mask) == 0:
df.loc['cumsum'] = df.groupby('HorseId', group_keys=False)['FGrating'].apply(
lambda x: x.shift(fill_value=0).cumsum())
return df.loc['cumsum'] / df.groupby('HorseId')['FGrating'].cumcount()
else:
return df.loc[mask].groupby('HorseId', group_keys=False)['FGrating'].apply(
lambda x: x.shift().expanding().mean())
当我尝试运行代码时,我在以下行收到“正在尝试在 DataFrame 的切片副本上设置值”警告:
df.loc['cumsum'] = df.groupby('HorseId', group_keys=False)['FGrating'].apply(
lambda x: x.shift(fill_value=0).cumsum())
我看不出有问题的代码在哪里。你可以帮我吗?
答:
2赞
Phoenix
4/6/2023
#1
这是因为 df.loc['cumsum'] 不是对 DataFrame 中特定行的引用。在 if 语句中,将其更改为:
cumsum_df = df.groupby('HorseId', group_keys=False)['FGrating'].apply(
lambda x: x.shift(fill_value=0).cumsum())
df.loc[cumsum_df.index, 'cumsum'] = cumsum_df
return df['cumsum'] / df.groupby('HorseId')['FGrating'].cumcount()
这应该可以解决您的问题
0赞
Bogdan Doicin
4/6/2023
#2
警告消息指示该操作正在尝试从原始 DataFrame df 而不是原始 DataFrame 本身的切片副本上设置值。df.loc['cumsum'] = ...
当您使用索引或切片选择原始 DataFrame 的子集,然后就地修改该子集时,可能会发生这种情况。在某些情况下,pandas 会返回子集的副本,而不是原始 DataFrame 的视图,尝试修改此副本可能会导致意外行为。
在本例中,问题出在行 上,该行通过仅选择列“HorseId”和“FGrating”来创建一个新的 DataFrame,该 DataFrame 是原始 df 的子集。这将创建子集的副本,而不是原始 DataFrame 的视图。df = df[['HorseId', 'FGrating']]
若要修复警告消息,可以修改代码以避免创建 DataFrame 的副本。执行此操作的一种方法是使用访问器在同一操作中同时选择行和列:loc
df = df.loc[:, ['HorseId', 'FGrating']]
这将选择所有行 (:) 以及列“HorseId”和“FGrating”。通过使用 loc 访问器,可以确保所选内容返回原始 DataFrame 的视图,而不是副本。
通过此更改,修改后的函数将是:
def compute_average_fg_rating(df, mask=''):
df = df.loc[:, ['HorseId', 'FGrating']]
if len(mask) == 0:
df.loc['cumsum'] = df.groupby('HorseId', group_keys=False)['FGrating'].apply(
lambda x: x.shift(fill_value=0).cumsum())
return df.loc['cumsum'] / df.groupby('HorseId')['FGrating'].cumcount()
else:
return df.loc[mask].groupby('HorseId', group_keys=False)['FGrating'].apply(
lambda x: x.shift().expanding().mean())
这应该可以解决警告消息。
评论