我有一个数据集,我想在该数据集上运行多个聚合步骤。这段代码创建数据:
import pandas as pd
import numpy as np
df1 = pd.DataFrame({'Name': ['A', 'A', 'B', 'B'],
'S': [200, 100, 300, 400],
'Date': pd.to_datetime(['2019-01-01', '2019-01-01', '2019-02-01', '2019-03-01']).date,
'Value': [5, 10, 30, 40]})
收益:
df1:
Name S Date Value
0 A 200 2019-01-01 5
1 A 100 2019-01-01 10
2 B 300 2019-02-01 30
3 B 400 2019-03-01 40
汇总的最终结果应如下所示:
2019-01-01 2019-02-01 2019-03-01
A 100, 200 15
B 300 - 400 30 40
我要做的第一步是
df2 = df.groupby(by=['Name', 'Date']).agg({'S': lambda x: ', '
.join(pd.DataFrame([str(s) for s in x]).drop_duplicates()
.sort_values(by=0)
.iloc[:, 0]
.map(str)),
'Value': np.sum,})
.join(...)
部分有些复杂,但是取S
中的数字,删除重复项,对其进行排序并将其连接为字符串。
结果是这样的:
df2:
S Value
Name Date
A 2019-01-01 100, 200 15
B 2019-02-01 300 30
2019-03-01 400 40
现在我被困住了。我可以生成以下内容:
df3 = (df2.pivot_table('Value', index=['Name', 'S'], columns=['Date'],
aggfunc={'Value': np.sum})
.fillna(0)
.reset_index()
)
df3:
Date Name S 2019-01-01 2019-02-01 2019-03-01
0 A 100, 200 15.0 0.0 0.0
1 B 300 0.0 30.0 0.0
2 B 400 0.0 0.0 40.0
但是,我希望将最后两行合并,S
变成300 - 400
(类似于df2
的联接)。我尚未发现如何将这些聚合合并为一个步骤(混合groupby
和pivot_table
)。
感谢您的帮助。
答案 0 :(得分:1)
尝试一下:
val=df1.groupby(['Name','Date'])['Value'].sum().reset_index() # get aggregate sum of values
ind=df1.groupby('Name').apply(lambda x: '-'.join([str(i) for i in x.S.values])).reset_index() # Prepare index for target dataframe
target_df=ind.merge(val, on=['Name']).pivot_table(index=['Name', 0], columns=['Date'], values='Value').fillna(0) # Merge both and pivot to get desired output
然后,print(target_df)
提供所需的输出:
Date 2019-01-01 2019-02-01 2019-03-01
Name 0
A 200-100 15.0 0.0 0.0
B 300-400 0.0 30.0 40.0
答案 1 :(得分:0)
@Parth给出了正确的见解,不可能同时执行两个步骤(汇总数字和pivot_table
数据,并同时运行groupby
),但是您必须分开创建未来索引,然后对数据进行透视。
这是我的最终代码(与@parth的代码略有不同):
import pandas as pd
import numpy as np
df1 = pd.DataFrame({'Name': ['A', 'A', 'B', 'B'],
'S': [200, 100, 300, 400],
'Date': pd.to_datetime(['2019-01-01', '2019-01-01', '2019-02-01', '2019-03-01']).date,
'Value': [5, 10, 30, 40]})
print('df1: \n', df1, '\n')
df2 = df.groupby(by=['Name', 'Date']).agg({'S': lambda x: ', '
.join(pd.DataFrame([str(s) for s in x]).drop_duplicates()
.sort_values(by=0)
.iloc[:, 0]
.map(str)),
'Value': np.sum,})
print('df2:\n ', df2, '\n')
ind = (df2.groupby(by=['Name']).agg({'S': lambda x: ' - '.join(pd.DataFrame([str(s) for s in x])
.drop_duplicates()
.sort_values(by=0)
.iloc[:, 0]
.map(str))})
.reset_index())
print('ind:\n', ind, '\n')
val = df1.groupby(['Name','Date'])['Value'].sum().reset_index() # get aggregate sum of values
print('val:\n', val, '\n')
df3 = (ind.merge(val, on=['Name'])
.pivot_table(index=['Name', 'S'], columns=['Date'], values='Value')
.fillna(0)
)
print('df3\n', df3)