Pandas groupby 使用两次应用时会复制组
Posted
技术标签:
【中文标题】Pandas groupby 使用两次应用时会复制组【英文标题】:Pandas groupby is duplicating groups when using apply twice 【发布时间】:2020-05-10 09:15:02 【问题描述】:pandas groupby 可以使用groupby.apply(func)
并在func
内部使用.apply()
的另一个实例而不复制和覆盖数据吗?
在某种程度上,.apply()
的使用是嵌套的。
Python 3.7.3
pandas==0.25.1
import pandas as pd
def dummy_func_nested(row):
row['new_col_2'] = row['value'] * -1
return row
def dummy_func(df_group):
df_group['new_col_1'] = None
# apply dummy_func_nested
df_group = df_group.apply(dummy_func_nested, axis=1)
return df_group
def pandas_groupby():
# initialize data
df = pd.DataFrame([
'country': 'US', 'value': 100.00, 'id': 'a',
'country': 'US', 'value': 95.00, 'id': 'b',
'country': 'CA', 'value': 56.00, 'id': 'y',
'country': 'CA', 'value': 40.00, 'id': 'z',
])
# group by country and apply first dummy_func
new_df = df.groupby('country').apply(dummy_func)
# new_df and df should have the same list of countries
assert new_df['country'].tolist() == df['country'].tolist()
print(df)
if __name__ == '__main__':
pandas_groupby()
上面的代码应该返回
country value id new_col_1 new_col_2
0 US 100.0 a None -100.0
1 US 95.0 b None -95.0
2 CA 56.0 y None -56.0
3 CA 40.0 z None -40.0
但是,代码返回
country value id new_col_1 new_col_2
0 US 100.0 a None -100.0
1 US 95.0 a None -95.0
2 US 56.0 a None -56.0
3 US 40.0 a None -40.0
仅当两个组的行数相等时才会出现此行为。如果一组有更多行,则输出如预期。
【问题讨论】:
【参考方案1】:在使用 groupby 时,我们应该避免在使用 apply() 的函数中使用 apply() 方法
产生所需结果的正确代码如下。
免责声明:可以更有效地编写代码。目的是为了证明我们应该避免在groupby.apply()
内部调用apply()
方法。如果我们应用它的组在每个组中具有相同数量的行,则会产生不利影响。如果每组中的行数不相等,则一切顺利。同样,这只发生在组具有相同数量的行时。
致用户:u10-forward
import pandas as pd
def dummy_func_nested(df):
df['new_col_2'] = df['value'] * -1
return df
def dummy_func(df_group):
df_group['new_col_1'] = None
# apply dummy_func_nested
df_group = dummy_func_nested(df_group)
return df_group
def pandas_groupby():
# initialize data
df = pd.DataFrame([
'country': 'US', 'value': 100.00, 'id': 'a',
'country': 'US', 'value': 95.00, 'id': 'b',
'country': 'CA', 'value': 56.00, 'id': 'y',
'country': 'CA', 'value': 40.00, 'id': 'z',
])
# group by country and apply first dummy_func
new_df = df.groupby('country').apply(dummy_func)
# new_df and df should have the same list of countries
assert new_df['country'].tolist() == df['country'].tolist()
print(df)
if __name__ == '__main__':
pandas_groupby()
也就是说,我仍然认为这是一个错误,无法在 groupby.apply()
中调用 apply()
方法。
【讨论】:
【参考方案2】:引用documentation:
在当前实现中,apply 在第一列/行上调用 func 两次,以决定它是否可以采用快速或慢速代码路径。如果 func 有副作用,这可能会导致意外行为,因为它们会对第一列/行生效两次。
尝试在您的代码中更改以下代码:
def dummy_func(df_group):
df_group['new_col_1'] = None
# apply dummy_func_nested
df_group = df_group.apply(dummy_func_nested, axis=1)
return df_group
收件人:
def dummy_func(df_group):
df_group['new_col_1'] = None
# apply dummy_func_nested
df_group = dummy_func_nested(df_group)
return df_group
您不需要apply
。
当然,更有效的方法是:
df['new_col_1'] = None
df['new_col_2'] = -df['value']
print(df)
或者:
print(df.assign(new_col_1=None, new_col_2=-df['value']))
【讨论】:
我记得在文档中读到过,然后马上就忘记了,很好! 使用dummy_func_nested(df_group)
而不是df_group.apply(dummy_func_nested, axis=1)
会导致此输出gist.github.com/olehdubno/0bc25b11c1efe3dd83b955a39f2422f7 输出显示原始组,但行仍被另一个组的副本覆盖。
我运行了代码,似乎得到了您想要的输出,但似乎无法重现您的输出。你在做什么来得到那个输出?
使用独立于apply()
的dummy_func_nested()
,即df_group = dummy_func_nested(df_group)
,会产生所需的结果。不知道我跑了什么导致框架以一种奇怪的方式显示。我的理解是,我们不应该在使用 groupby 的其他 apply()
方法中调用 apply()
方法。我们应该直接应用函数而不是使用apply。
@OlehDubno 请接受并支持它的工作原理:-)以上是关于Pandas groupby 使用两次应用时会复制组的主要内容,如果未能解决你的问题,请参考以下文章
为啥我在 pandas 中的 groupby 后会出现“关键错误”? [复制]
带有 pandas、groupby、子图、计算/描述性统计、聚合的箱线图