【问题标题】:In Python, how to do group by + mutate + ifelse like R?在 Python 中,如何像 R 一样进行 group by + mutate + ifelse?
【发布时间】:2018-04-23 04:13:22
【问题描述】:

我通常使用 R。如果我有这样的数据:

Product    Index   Value
   a         1       0.5
   a         1       0.4
   c         1       1.4
   c         2       0.75
   e         2       0.6
   f         3       0.9

如果我的 R 代码是:

a <- data %>%
  group_by(Product) %>%
  mutate(Flag=ifelse(all(Index==1),'right','wrong'))

这意味着,我首先按产品对数据进行分组。然后对于每个组,我会给它一个名为 Flag 的新字段。如果该组中的Index全为1,则Flag为对,否则为错。同时,所有记录都保留下来。所以,结果应该是这样的:

Product    Index   Value    Flag
   a         1       0.5    right
   a         1       0.4    right
   c         1       1.4    wrong
   c         2       0.75   wrong
   e         2       0.6    wrong
   f         3       0.9    wrong

我的问题是:如何在 python 中执行相同的操作?我试过,np.where、groupby、transform等功能。我可能以错误的方式将它们组合在一起。

【问题讨论】:

    标签: python transform dplyr


    【解决方案1】:

    使用变换是一种选择。

    import pandas as pd
    
    df = pd.DataFrame({'Product': ['a', 'a', 'c', 'c', 'e', 'f'],
                   'Index': [1, 1, 1, 2, 2, 3], 
                  'Value': [0.5, 0.4, 1.4, 0.75, 0.6, 0.9]})
    df['Flag'] = df.groupby('Product')['Index'].transform(lambda x: 'right' if sum(x)/len(x) == 1 else 'wrong')
    df
    

    附带说明,如果 Flag 值只是“正确”和“错误”,用 0,1 值替换它们可能更有效。

    【讨论】:

    • 也许这更通用(可用于字符串等): df['Flag'] = df.groupby('Product')['Index'].transform(lambda x: 'right ' if all(x==1) else '错误')
    • 非常感谢。太好了。
    • 您也可以使用布尔值进行子集化:df['Flag'] = df.groupby('Product')['Index'].transform(lambda i: ['wrong', 'right'][all(i == 1)])
    【解决方案2】:

    您可以使用unique()groupby() 确保所有产品的索引为1,然后映射到您的新列:

    In [51]: df['Flag'] = df['Product'].map(df.groupby('Product')['Index'].unique().apply(lambda row: 'right' if all(row==[1]) else 'wrong'))
    
    In [52]: df
    Out[52]:
      Product  Index  Value   Flag
    0       a      1   0.50  right
    1       a      1   0.40  right
    2       c      1   1.40  wrong
    3       c      2   0.75  wrong
    4       e      2   0.60  wrong
    5       f      3   0.90  wrong
    

    【讨论】:

      【解决方案3】:

      使用GroupBy.transformmean,按条件比较1numpy.where 的值:

      df['Flag'] = np.where(df.groupby('Product')['Index'].transform('mean')== 1, 'right', 'Wrong')
      print (df)
        Product  Index  Value   Flag
      0       a      1   0.50  right
      1       a      1   0.40  right
      2       c      1   1.40  Wrong
      3       c      2   0.75  Wrong
      4       e      2   0.60  Wrong
      5       f      3   0.90  Wrong
      

      详情

      print (df.groupby('Product')['Index'].transform('mean'))
      0    1.0
      1    1.0
      2    1.5
      3    1.5
      4    2.0
      5    3.0
      Name: Index, dtype: float64
      

      另一种解决方案:

      首先通过1eq 进行比较,然后将GroupBy.transformall 进行比较,以检查每个组中是否所有Trues 和numpy.where 按条件检查值:

      df['Flag'] = np.where(df['Index'].eq(1).groupby(df['Product']).transform('all'), 
                            'right', 'Wrong')
      print (df)
        Product  Index  Value   Flag
      0       a      1   0.50  right
      1       a      1   0.40  right
      2       c      1   1.40  Wrong
      3       c      2   0.75  Wrong
      4       e      2   0.60  Wrong
      5       f      3   0.90  Wrong
      

      详情

      print (df['Index'].eq(1).groupby(df['Product']).transform('all'))
      0     True
      1     True
      2    False
      3    False
      4    False
      5    False
      Name: Index, dtype: bool
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-01-10
        • 2022-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多