【问题标题】:Python: group by sum with conditionPython:按条件按总和分组
【发布时间】:2018-12-10 16:39:47
【问题描述】:

我有一个如下的数据框:

df = pd.DataFrame({'condition' : ['a','b','b','b','a','a'],
               'name' : ['one', 'one', 'two', 'three', 'three', 'three'],
               'data1' : [7, 3, 48, 13, 27, 12]})
df
  condtion  data1   name
0   a          7    one
1   b          3    one
2   b         48    two
3   b         13    three
4   a         27    three
5   a         12    three

对于每个名字,我想在data1 上求和,如果我有这些信息,则使用condition=a 的信息,否则使用condition=b。最后,我想要一个如下所示的数据框:

df1 
    name   total
0   one      7
1   two     48
2   three   39

【问题讨论】:

标签: python pandas dataframe group-by


【解决方案1】:

您可以聚合 groupby 和聚合 sum 并通过 unstack 重塑,最后用 fillna 替换缺失类别 a 的 NaN:

df = df.groupby(['name','condition'], sort=False)['data1'].sum().unstack()
df['total'] = df['a'].fillna(df['b'])
print (df)
condition     a     b  total
name                        
one         7.0   3.0    7.0
two         NaN  48.0   48.0
three      39.0  13.0   39.0

对于新的DataFrame

df1 = df.reset_index().rename_axis(None, 1)[['name','total']]
print (df1)
    name  total
0    one    7.0
1    two   48.0
2  three   39.0

apply 的另一个解决方案:

def f(x):
    if (x['condition'] == 'a').any():
        return x.loc[x['condition'] == 'a', 'data1'].sum() 
    else:
        return x.loc[x['condition'] == 'b', 'data1'].sum()

df1 = df.groupby('name', sort=False).apply(f).reset_index(name='total')
print (df1)
    name  total
0    one      7
1    two     48
2  three     39

更好的方法是创建 Series 来聚合过滤后的 DataFrame,然后创建 combine_first,但此解决方案省略了所有没有 ab 条件的 names 组:

a = df.loc[df['condition'] == 'a'].groupby('name', sort=False)['data1'].sum()
b = df.loc[df['condition'] == 'b'].groupby('name', sort=False)['data1'].sum()

df = a.combine_first(b).reset_index(name='total')
print (df)
    name  total
0    one    7.0
1  three   39.0
2    two   48.0

【讨论】:

    【解决方案2】:

    您可以通过groupbynamecondition 找到data1sum,然后通过namecondition 找到sort_values,然后为@987654331 分组中的每个组选择第一个条目@:

    df.groupby(['name', 'condition'])['data1'].sum().reset_index(name='total').sort_values(['name','condition']).groupby(['name']).first().reset_index()[['name', 'total']]
    

    输出:

        name    total
    0   one     7
    1   three   39
    2   two     48
    

    【讨论】:

      【解决方案3】:

      您可以将pd.pivot_tableaggfunc='sum' 一起使用:

      df = pd.DataFrame({'condition' : ['a','b','b','b','a','a'],
                         'name' : ['one', 'one', 'two', 'three', 'three', 'three'],
                         'data1' : [7, 3, 48, 13, 27, 12]})
      
      res = df.pivot_table(index='name', columns='condition', values='data1', aggfunc='sum')
      
      condition     a     b
      name                 
      one         7.0   3.0
      three      39.0  13.0
      two         NaN  48.0
      

      然后申请fillna并清理:

      res = res.assign(total=res['a'].fillna(res['b']).astype(int))\
               .reset_index().rename_axis('', 1)\
               .loc[:, ['name', 'total']]
      
      print(res)
      
          name  total
      0    one      7
      1  three     39
      2    two     48
      

      【讨论】:

        猜你喜欢
        • 2019-06-18
        • 1970-01-01
        • 2021-04-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-22
        • 2020-05-11
        相关资源
        最近更新 更多