df
date Box size loc
1.1.20 abc 2 K
1.1.20 def 1 K
1.1.20 ghi 1 B
2.1.20 jkl 2 D
2.1.20 mno 1 D
2.1.20 pqr 1 E
2.1.20 stu 2 E
3.1.20 vwx 2 K
3.1.20 wer 2 D
3.1.20 cba 1 E
4.1.20 fde 2 B
4.1.20 gfd 1 B
5.1.20 lad 2 K
5.1.20 res 2 E
5.1.20 bgf 2 D
5.1.20 psa 2 D
期望的输出:按日期和大小的总和分组,然后按值计数和求和。
Date Size B_count B_sum D_count D_sum E_count E_sum K_count K_sum
0 2020-01-01 4.0 1 1 0 0 0 0 2 3
1 2020-02-01 6.0 0 0 2 3 2 0 0 3
2 2020-03-01 5.0 0 0 1 2 1 1 1 2
3 2020-04-01 3.0 2 3 0 0 0 0 0 0
3 2020-05-01 8.0 0 0 2 4 1 2 1 2
我以不同的方式尝试了以下方法,但只能达到所需的 50%。
df_pivot_1 = pd.get_dummies(df, columns=['loc'], prefix='', prefix_sep='').groupby(['date']).sum('size').reset_index()
``
答案 0 :(得分:2)
使用 GroupBy.agg
聚合 count
和 sum
,然后通过 DataFrame.unstack
重塑并使用展平列进行排序,对于 Size
列使用 {{3} } 对于由每 Date
秒的总和值填充的第一列:
df11 = df.groupby(['date','loc'])['size'].agg(['count','sum'])
df1 = df11.unstack(fill_value=0).sort_index(axis=1, level=1)
df1.columns = [f'{b}_{a}' for a, b in df1.columns]
df1.insert(0, 'Size', df11['sum'].sum(level=0))
print (df1)
Size B_count B_sum D_count D_sum E_count E_sum K_count K_sum
date
1.1.20 4 1 1 0 0 0 0 2 3
2.1.20 6 0 0 2 3 2 3 0 0
3.1.20 5 0 0 1 2 1 1 1 2
4.1.20 3 2 3 0 0 0 0 0 0
5.1.20 8 0 0 2 4 1 2 1 2
感谢@anky 的建议 - 您可以选择 sum
列并每行求和:
df['date'] = pd.to_datetime(df['date'], format='%d.%m.%y')
df11 = df.groupby(['date','loc'])['size'].agg(['count','sum'])
df1 = df11.unstack(fill_value=0).sort_index(axis=1, level=1)
s = df1.xs('sum', level=0, axis=1).sum(axis=1)
df1.columns = [f'{b}_{a}' for a, b in df1.columns]
df1.insert(0, 'Size', s)
df1 = df1.reset_index()
类似的用法是pivot_table
:
df11 = df.pivot_table(index='date',
columns='loc',
values='size',
aggfunc=['count','sum'],
fill_value=0)
df1 = df11.sort_index(axis=1, level=1)
s = df1.xs('sum', level=0, axis=1).sum(axis=1)
df1.columns = [f'{b}_{a}' for a, b in df1.columns]
df1.insert(0, 'Size', s)
df1 = df1.reset_index()
答案 1 :(得分:0)
另一种选择是使用 pivot_wider 中的 pyjanitor 函数,它是 pivot/groupby
的便捷包装器:
(df.pivot_wider(index='date',
names_from='loc',
aggfunc=['count', 'sum'],
values_from='size',
fill_value = 0,
names_sort=True)
.assign(size = lambda df: df.filter(like='sum').sum(1))
)
date B_count B_sum D_count D_sum E_count E_sum K_count K_sum size
0 2020-01-01 1 1 0 0 0 0 2 3 4
1 2020-01-02 0 0 2 3 2 3 0 0 6
2 2020-01-03 0 0 1 2 1 1 1 2 5
3 2020-01-04 2 3 0 0 0 0 0 0 3
4 2020-01-05 0 0 2 4 1 2 1 2 8