具有多个输出的熊猫数据框

时间:2021-03-30 12:22:13

标签: python pandas

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()
``

2 个答案:

答案 0 :(得分:2)

使用 GroupBy.agg 聚合 countsum,然后通过 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