【问题标题】:Preserve the non-numerical columns when doing pandas.DataFrame.groupby().sum()执行 pandas.DataFrame.groupby().sum() 时保留非数字列
【发布时间】:2018-04-21 00:06:10
【问题描述】:

我可以在做 pandas.DataFrame.groupby().sum() 时保留非数字列(第一个出现的值)吗?

例如,我有一个这样的 DataFrame:

df = pd.DataFrame({'A' : ['aa1', 'aa2', 'aa1', 'aa2'],'B' : ['bb1', 'bbb1', 'bb2', 'bbb2'],'C' : ['cc1', 'ccc2', 'ccc3', 'ccc4'],'D' : [1, 2, 3, 4],'E' : [1, 2, 3, 4]})
>>> df
     A     B     C  D  E
0  aa1   bb1   cc1  1  1
1  aa2  bbb1  ccc2  2  2
2  aa1   bb2  ccc3  3  3
3  aa2  bbb2  ccc4  4  4
>>> df.groupby(["A"]).sum()
     D  E
A        
aa1  4  4
aa2  6  6

以下是我想要得到的结果:

     B    C    D  E
A        
aa1  bb1  cc1  4  4
aa2  bbb1 ccc2 6  6

注意BC列的值是每个组键的第一个关联的B值和C值。

【问题讨论】:

  • 您是说要按A 分组并按B in reverse 排序,这有点令人困惑,您能用可用的df 解释您的预期结果吗?
  • 其实我想在df.groupby(["A"]).sum()的结果中加入B这一列,结果B的值就是分组的第一个B值。
  • 嗨@AaronWang,欢迎来到stackoverflow!我相信您想使用保留一词而不是保留,如果是这样,请编辑您的问题,以便将来有类似问题的其他人很容易找到。另外,正如您在 cmets 中所说,请在您的帖子中包含“您想找到每个组键的第一个关联 B 值”。谢谢!

标签: python pandas


【解决方案1】:

只需使用'first':

df.groupby(["A"]).agg({'B': 'first',
                       'C': 'first',
                       'D': sum,
                       'E': sum})

【讨论】:

    【解决方案2】:

    对于 groupby-sum 数据框中的每个键,在原始数据框中查找键,并将列 B 的关联值放入新列。

    #groupby and sum over columns C and D
    df_1 = df.groupby(['A']).sum()
    

    在 B 列中查找与 groupby 键关联的第一个值

    groupby keys
    col_b = []
    #iterate through keys and find the the first value in df['B'] with that key in column A
    for i in df_1.index:
        col_b.append(df['B'][df['A'] == i].iloc[0])
    
    #insert list of values into new dataframe
    df_1.insert(0, 'B', col_b)
    >>>df_1
          B  D  E
    A           
    aa1 bb1  4  4
    aa2 bbb1 6  6
    

    【讨论】:

    • 我在做pandas.DataFrame.groupby().sum()时可以保留所有非数字列吗
    • @AaronWang 您能否编辑您的问题,以更好地反映您的意思?我已根据您的 cmets 编辑了我的答案。
    • 是的,你明白了。谢谢!该代码可能有点“丑陋”但很有用。如果我有很多像 B 这样的列,代码会更复杂。现在我觉得pandas中没有这个功能的api,哈哈
    【解决方案3】:

    仅在“A”列上分组给出:

    df.groupby(['A']).sum()
    
            C     D
    A              
    bar  1.26  0.88
    foo  0.92 -4.19
    

    在“A”和“B”列上分组给出:

    df.groupby(['A','B']).sum()
    
                C     D
    A   B                
    bar one    1.38 -0.73
        three  0.26  0.80
        two   -0.38  0.81
    foo one    1.96 -2.72
        three -0.42 -0.18
        two   -0.62 -1.29
    

    如果您只想要具有“one”的列“B”,您可以这样做:

    d = df.groupby(['A','B'], as_index=False).sum()
    d[d.B=='one'].set_index('A')
    
        B     C     D
    A                   
    bar  one  1.38 -0.73
    foo  one  1.96 -2.72
    

    我不确定我是否理解,但这是您想要做的吗? 注意:我增加了输出精度只是为了获得与帖子中显示的相同的数字。

    d = df.groupby('A').sum()
    d['B'] = 'one'
    d.sort_index(axis=1)
    
           B         C         D
    A                           
    bar  one  1.259069  0.876959
    foo  one  0.921510 -4.193397
    

    如果您想将列的第一个排序值从 'B' 开始,您可以使用:

    d['B'] = df.B.sort(inplace=False)[0]
    

    所以在这里我用 'a', 'b','c' 替换了 'one','two','three' 看看这是否是你想要做的,并按照建议使用 insert() 方法通过其他帖子

    df
    
        A  B         C         D
    0  foo  a  0.638362 -0.931817
    1  bar  a  1.380706 -0.733307
    2  foo  b -0.324514  0.203515
    3  bar  c  0.258534  0.803298
    4  foo  b -0.299485 -1.495979
    5  bar  b -0.380171  0.806968
    6  foo  a  1.324810 -1.792996
    7  foo  c -0.417663 -0.176120
    
    d = df.groupby('A').sum()
    d.insert(0, 'B', df.B.sort(inplace=False)[0])
    d
    
        B         C         D
    A                         
    bar  a  1.259069  0.876959
    foo  a  0.921510 -4.193397
    

    【讨论】:

    • 其实我想在df.groupby(["A"]).sum()的结果中加入B这一列,结果B的值就是分组的第一个B值。 CD的值不是我想要的d[d.B=='one'].set_index('A')中的值,而B的值不一定都是“一”,它的值是df.groupby(['A','B']).sum()的第一个B值跨度>
    • 发布的“期望值”与仅在“A”上分组相同。我假设所需的结果是对 A 和 B 进行分组,但只选择具有“一个”的 B 列。如果所需的结果是仅在“A”上分组,然后在每个条目中插入一个新列“B”,也可以这样做。
    • @AaronWang 我想我明白了,请检查上面的最终编辑
    • 是的,你明白了。谢谢!代码可能“丑陋”但很有用。如果我有很多像B 这样的列,代码会更复杂。现在我觉得pandas中没有这个功能的api,哈哈
    • @SteveMisuta 如果进行排序,则不会得到每组对应的第一个值,而只会得到 B 列的前 2 个值。
    【解决方案4】:

    所有这些答案似乎都很冗长;尽管在第一页给出了一个 SQL 示例,但 Pandas 文档 [1] 在这一点上似乎也不清楚:

    SELECT Column1, Column2, mean(Column3), sum(Column4)
    FROM SomeTable
    GROUP BY Column1, Column2
    

    它将选择 Column1 的“第一个”,Column2,而 Pandas 不会。正如 OP 指出的那样,非数字列被简单地删除了。我的解决方案也不是那么漂亮,但也许更多的控制是 Pandas 的设计目标:

    agg_d = { c: 'sum' if c == 'A' else 'first' for c in df.columns }
    df = df.groupby( df['A'] ).agg( agg_d )
    

    这维护所有非数字列,就像 sql 一样。这与下面 Phillip 的回答基本相同,但不需要显式枚举列。

    注意事项

    1. https://pandas.pydata.org/pandas-docs/stable/groupby.html

    【讨论】:

      猜你喜欢
      • 2021-09-26
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 2017-01-15
      • 1970-01-01
      • 2019-01-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多