【问题标题】:pandas- new calculated row for each unique string/group in a columnpandas- 为列中每个唯一字符串/组的新计算行
【发布时间】:2019-05-30 06:56:04
【问题描述】:

我有一个数据框df,比如:

GROUP  TYPE  COUNT
A       1     5
A       2     10
B       1     3
B       2     9
C       1     20
C       2     100

我想为每个组添加一行,以便新行计算COUNT 的商,其中TYPE 等于2 和COUNT,其中TYPE 等于1 对于每个GROUP ala:

GROUP  TYPE  COUNT
A       1     5
A       2     10
A             .5
B       1     3
B       2     9
B             .33
C       1     20
C       2     100
C             .2

提前致谢。

【问题讨论】:

  • 每个组是否总是只有 2 个条目,每种类型一个?
  • 有时一个组有两个以上的types,但我只想将type 2 除以type 1
  • 好的,每个组中的每种类型只有一行?

标签: python pandas dataframe for-loop


【解决方案1】:
df2 = df.pivot(index='GROUP', columns='TYPE', values='COUNT')
df2['div'] = df2[1]/df2[2]
df2.reset_index().melt('GROUP').sort_values('GROUP')

输出:

  GROUP TYPE       value
0     A    1    5.000000
3     A    2   10.000000
6     A  div    0.500000
1     B    1    3.000000
4     B    2    9.000000
7     B  div    0.333333
2     C    1   20.000000
5     C    2  100.000000
8     C  div    0.200000

我的方法是通过旋转来重塑数据框,因此每种类型都有自己的列。然后分割很容易,然后通过熔化将其重塑回原始形状。在我看来,这也是一个可读性很强的解决方案。

当然,如果你更喜欢 np.nan 而不是 div 作为类型,你可以很容易地替换它,但我不确定这是否是你想要的。

【讨论】:

    【解决方案2】:
    s=df[df.TYPE.isin([1,2])].sort_values(['GROUP','TYPE']).groupby('GROUP').COUNT.apply(lambda x : x.iloc[0]/x.iloc[1])
    # I am sort and filter your original df ,to make they are ordered and only have type 1 and 2 
    pd.concat([df,s.reset_index()]).sort_values('GROUP') 
    # cancat your result back 
    
    Out[77]: 
            COUNT GROUP  TYPE
    0    5.000000     A   1.0
    1   10.000000     A   2.0
    0    0.500000     A   NaN
    2    3.000000     B   1.0
    3    9.000000     B   2.0
    1    0.333333     B   NaN
    4   20.000000     C   1.0
    5  100.000000     C   2.0
    2    0.200000     C   NaN
    

    【讨论】:

      【解决方案3】:

      你可以这样做:

      import numpy as np
      import pandas as pd
      
      def add_quotient(x):
          last_row = x.iloc[-1]
          last_row['COUNT'] = x[x.TYPE == 1].COUNT.min() / x[x.TYPE == 2].COUNT.max()
          last_row['TYPE'] = np.nan
          return x.append(last_row)
      
      
      print(df.groupby('GROUP').apply(add_quotient))
      

      输出

              GROUP  TYPE       COUNT
      GROUP                          
      A     0     A   1.0    5.000000
            1     A   2.0   10.000000
            1     A   NaN    0.500000
      B     2     B   1.0    3.000000
            3     B   2.0    9.000000
            3     B   NaN    0.333333
      C     4     C   1.0   20.000000
            5     C   2.0  100.000000
            5     C   NaN    0.200000
      

      请注意,该函数选择TYPE == 1 的最小值和TYPE == 2 的最大值,以防每组有多个值。并且 TYPE 设置为np.nan,但可以轻松更改。

      【讨论】:

        【解决方案4】:

        这是一种首先使用sort_values' by '['GROUP', 'TYPE'] 的方法,以确保TYPE 2 出现在1 之前,然后是GroupBy GROUP

        然后使用firstlast 计算与df 的quocient 和outer 合并:

        g = df.sort_values(['GROUP', 'TYPE']).groupby('GROUP')
        s = (g.first()/ g.nth(1)).COUNT.reset_index()
        df.merge(s, on = ['GROUP','COUNT'], how='outer').fillna(' ').sort_values('GROUP')
        
           GROUP TYPE       COUNT
        0     A    1    5.000000
        1     A    2   10.000000
        6     A         0.500000
        2     B    1    3.000000
        3     B    2    9.000000
        7     B         0.333333
        4     C    1   20.000000
        5     C    2  100.000000
        8     C         0.200000
        

        【讨论】:

        • 这只有在只有两种类型时才有效,提问者在 cmets 中说的情况并非总是如此。
        • type 0 怎么样。一般来说,我会避免相对定位
        猜你喜欢
        • 1970-01-01
        • 2020-03-07
        • 1970-01-01
        • 1970-01-01
        • 2020-01-19
        • 2021-07-27
        • 2016-11-13
        相关资源
        最近更新 更多