python - pandas groupby 仅聚合两个连续字段之间共有的行
问题描述
我正在尝试计算每个date
字段的总和,但是我只想计算 current 和 next中的 ID 总和date
,因此rolling
先比较 ID,然后计算groupby
总和。目前我必须遍历非常慢的数据帧。
例如我的df:
df = pd.DataFrame({
'Date': [1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4],
'ID': [ 1, 2, 3, 4 , 2, 3, 4 , 2, 3, 4, 5, 1, 2, 3, 4],
'Value': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
})
理想情况下,我想对数据框进行分组,Date
并且只对两个日期之间的共同点进行求和IDs
,例如下面。然而,这是非常缓慢的。
tmpL = df.groupby('Date')['ID'].apply(list)
tmpV = df.groupby('Date')['Value'].sum()
for i in range(1, tmpL.shape[0]):
res = list(set(tmpL.iloc[i]) - set(tmpL.iloc[i - 1]))
v = df.loc[ df.ID.isin(res) & (df.Date == tmpL.index[i]), 'Value'].sum()
tmpV.iloc[i] = tmpV.iloc[i] - v
tmpV
Date
1 10
2 18
3 27
4 42
Name: Value, dtype: int64
有没有办法在pandas
不循环数据帧的情况下做到这一点?
解决方案
使用DataFrame.pivot_table
with aggregate sum
,比较不等于 with DataFrame.diff
,最后传递给DataFrame.mask
with sum
:
df1 = df.pivot_table(index='Date', columns='ID', values='Value', aggfunc='sum')
s = df1.mask(df1.notna().diff().fillna(False)).sum(axis=1)
print (s)
Date
1 10.0
2 18.0
3 27.0
4 42.0
dtype: float64
第一个解决方案,我认为更慢:
您可以通过将 original 转换为 s 来获取所有不匹配的集合set
,然后使用Series.diff
,并通过、last 聚合和减去Series.explode
来获取 original 的所有匹配值:DataFrame.merge
sum
tmpL = (df.groupby('Date')['ID'].apply(set)
.diff()
.explode()
.reset_index()
.merge(df)
.groupby('Date')['Value']
.sum())
tmpV = df.groupby('Date')['Value'].sum()
out = tmpV.sub(tmpL, fill_value=0)
print (out)
Date
1 10.0
2 18.0
3 27.0
4 42.0
推荐阅读
- css - 尝试使用 CSS 隐藏 div
- java - spring,prototype和singleton有性能上的区别吗?
- r - R 包 'ps' 安装失败,因为在安装的最后一步拒绝了 mv 的权限
- twilio-functions - 如何在 Twilio Functions 中安全地存储电话号码?
- react-native - 类型错误:Method.bind 不是函数
- python - 您如何列出具有相同外键对象的所有对象?
- c++ - std::list of move-only type: 在 VC++ 中不能进入 std::vector
- ansible - 如何组合一堆具有相同缓慢设置和拆卸的 Ansible 剧本?
- java - 如何从 javafx.scene.image.Image 对象中获取字节数组?
- sockets - boost async_accept 不适用于 boost asio use_future 选项