【问题标题】:To compare the values responding the different categories for each group(using groupby)比较响应每个组的不同类别的值(使用 groupby)
【发布时间】:2022-01-22 23:52:56
【问题描述】:

我尝试为每个组的状态应用规则。 规则将是: 如果角 A 和 D 的值都小于角 B 和 C 的值,则该组的状态将为通过。否则会失败。

下面是数据框 df。

Item    Corner   Value   
A-001     A       0.1
A-001     B       0.5
A-001     C       0.4
A-001     D       0.1
A-002     A       0.3
A-002     B       0.6
A-002     C       0.2
A-002     D       0.1

以及预期的结果:

Item    Corner   Value   Status
A-001     A       0.1      pass (corner A &D < corner B&C)
A-001     B       0.5      pass
A-001     C       0.4      pass
A-001     D       0.1      pass
A-002     A       0.3      fail (corner A > corner C, so the status of this group failed)
A-002     B       0.6      fail
A-002     C       0.2      fail
A-002     D       0.1      fail

所以,这是我的解决方案,但功能仍然不完整......

def rule_status(df):
    
    corner_a = df.loc[df['corner'] == 'A', 'Value']
    corner_b = df.loc[df['corner'] == 'B', 'Value']
    corner_c = df.loc[df['corner'] == 'C', 'Value']
    corner_d = df.loc[df['corner'] == 'D', 'Value']

    if max(corner_a, corner_d) < min(corner_b, corner_c):
        return 'pass' 
    else:
        return 'fail'    

df.groupby('Item').apply(lambda x :rule_status(x))

但是,在函数中,我只得到corner_acorner_bcorner_c &corner_d的一系列值,而不是每个角的具体值。

【问题讨论】:

    标签: python-3.x pandas dataframe pandas-groupby


    【解决方案1】:

    我建议你pivot数据然后比较:

    pivoted = df.pivot('Item', 'Corner', 'Value')
    
    mask = pivoted[['A','D']].max(axis=1) < pivoted[['B','C']].min(axis=1)
    
    df['Status'] = np.where(df['Item'].map(mask), 'pass', 'fail')
    

    输出:

        Item Corner  Value Status
    0  A-001      A    0.1   pass
    1  A-001      B    0.5   pass
    2  A-001      C    0.4   pass
    3  A-001      D    0.1   pass
    4  A-002      A    0.3   fail
    5  A-002      B    0.6   fail
    6  A-002      C    0.2   fail
    7  A-002      D    0.1   fail
    

    【讨论】:

    • 实际上,每个组有超过4个角,状态的比较比这复杂得多。但是,我只是试图简单地提出问题......
    • 复杂与否,您应该在 pivoted: mask = pivoted.apply(lambda r: max(r['A'], r['D']) &lt; min(r['B'], r['C']), axis=1) 上执行此操作。也就是说,您应该考虑如何对您的比较进行矢量化(如我的回答)。
    • 谢谢。不确定它是否会工作。但是,非常感谢您的解决方案。
    【解决方案2】:

    你可以使用:

    df['Status'] = df['Item'].map(
        df.loc[df['Corner'].isin(['A', 'D'])].groupby('Item')['Value'].max()
          .lt(df.loc[df['Corner'].isin(['B', 'C'])].groupby('Item')['Value'].min())
          .replace({True: 'pass', False: 'fail'}))
    print(df)
    
    # Output:
        Item Corner  Value Status
    0  A-001      A    0.1   pass
    1  A-001      B    0.5   pass
    2  A-001      C    0.4   pass
    3  A-001      D    0.1   pass
    4  A-002      A    0.3   fail
    5  A-002      B    0.6   fail
    6  A-002      C    0.2   fail
    7  A-002      D    0.1   fail
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-10
      • 1970-01-01
      • 2015-06-01
      • 1970-01-01
      • 2020-07-17
      • 1970-01-01
      相关资源
      最近更新 更多