我正在尝试使用pandas构建一个类似下面的数据框,其中如果当天有间隔1和3,Asum只获取一个值。我最接近工作的是使用它:
df['ASum']=df.groupby(level=['DateTime'])['A'].sum()
但是当我运行它时,它会一直向下返回NaN。关于如何做到这一点的任何想法都表示赞赏。
A B ASum
DateTime INT
2016-07-05 3 4700.0 4700.0 0
2016-07-06 1 5906.0 6830.0 0
3 1090.0 1090.0 6996
2016-07-07 1 7969.0 5273.0 0
3 1971.0 1971.0 9940
2016-07-08 1 3296.0 2764.0 0
3 1179.0 1179.0 4475
2016-07-11 1 4993.0 5798.0 0
3 1325.0 1325.0 6318
答案 0 :(得分:3)
这是一个基于取消堆叠INT
级别的解决方案,获取总和并将其堆叠回来。
import pandas as pd
midx = pd.MultiIndex(levels=[['2016-07-05', '2016-07-06', '2016-07-07',
'2016-07-08', '2016-07-11'], [1, 3]],
labels=[[0, 1, 1, 2, 2, 3, 3, 4, 4],
[1, 0, 1, 0, 1, 0, 1, 0, 1]],
names=['DateTime', 'INT'])
df = pd.DataFrame({'A': [4700.0, 5906.0, 1090.0, 7969.0, 1971.0,
3296.0, 1179.0, 4993.0, 1325.0],
'B': [4700.0, 6830.0, 1090.0, 5273.0, 1971.0,
2764.0, 1179.0, 5798.0, 1325.0]},
index=midx)
df = df.unstack(level='INT')
df[('Asum', 3)] = df['A'].sum(axis=1, skipna=False)
df = df.stack(level='INT').fillna(0)
print(df)
输出:
A B Asum
DateTime INT
2016-07-05 3 4700.0 4700.0 0.0
2016-07-06 1 5906.0 6830.0 0.0
3 1090.0 1090.0 6996.0
2016-07-07 1 7969.0 5273.0 0.0
3 1971.0 1971.0 9940.0
2016-07-08 1 3296.0 2764.0 0.0
3 1179.0 1179.0 4475.0
2016-07-11 1 4993.0 5798.0 0.0
3 1325.0 1325.0 6318.0
答案 1 :(得分:0)
df['ASum'] = 0 # the new column MUST be defined ahead
for idx,data in df.groupby(level=['DateTime']):
if all(x in data.index.get_level_values('INT') for x in [1,3]):
df.loc[idx,'ASum'].iloc[-1] = data['A'].sum() # adds the sum to the last row in the group only
结果如何:
A ASum
DateTime INT
2016-07-05 3 4700 0
2016-07-06 1 5906 0
3 1090 6996
2016-07-07 1 7967 0
3 1971 9938
2016-07-08 1 3296 0
3 119 3415
2016-07-11 1 4993 0
3 1325 6318
或,如果您希望总和显示在INT==3
的位置(并且不一定在最后一行):
df['ASum'] = 0
for idx,data in df.groupby(level=['DateTime']):
if all(x in data.index.get_level_values('INT') for x in [1,3]):
df.loc[(idx,3),'ASum'] = data['A'].sum() # << changed this line only
(直到我提出一些综合解决方案)