代码之家  ›  专栏  ›  技术社区  ›  Rahul Agarwal

在一个id中匹配多个列的值

  •  1
  • Rahul Agarwal  · 技术社区  · 7 年前

    样品DF:

    ID     Match1        Match2        Match3     Match4       Match5
    1      Yes           No            Yes        Yes          Yes
    2      Yes           No            Yes        Yes          No
    2      Yes           No            No         Yes          Yes
    3      No            Yes           Yes        Yes          No
    3      No            Yes           No         No           No
    4      Yes           No            Yes        No           No
    4      Yes           No            Yes        Yes          Yes
    

    预期DF:

     ID     Match1     Match2        Match3     Match4    Match5 Final_Match
        1      Yes      No            Yes        Yes      Yes     Clear
        2      Yes      No            Yes        Yes      No      Unclear
        2      Yes      No            No         Yes      Yes     Unclear
        3      No       Yes           Yes        Yes      No      Clear
        3      No       Yes           No         No       No      Unclear
        4      Yes      No            Yes        No       No      Unclear
        4      Yes      No            Yes        Yes      Yes     Clear
    

    问题陈述:

    1. 如果id是非重复的,简单地说 Clear 在里面 Final_Match 列(示例ID 1)
    2. 如果id是重复的,那么在id计数内 Yes 在match1到match5列中,以“yes”较大者为准 清除 为了那个 Unclear 对于另一个(示例ID 3和4

    3. 如果id是重复的,那么在id计数内 是的 在match1到match5列中,如果它们有相等的“yes”输入 不清楚的 两者(示例ID 2)

    我在身份证里找不到任何解决方法?

    0 回复  |  直到 7 年前
        1
  •  2
  •   Chris Adams    7 年前

    你也可以通过使用 Groupby.rank :

    # Helper Series
    s = (df.replace({'Yes': 1, 'No': 0})
         .iloc[:, 1:]
         .sum(1))
    
    df['final_match'] = np.where(s.groupby(df['ID']).rank(ascending=False).eq(1), 'Clear', 'Unclear')
    
        2
  •  2
  •   anky    7 年前

    另一种方法是:

    df['sum_yes']=df.iloc[:,1:6].eq('Yes').sum(axis=1)
    df['final']=df.groupby('ID')['sum_yes'].transform\
                 (lambda x: np.where((x==x.max())&(~x.duplicated(keep=False)),'Clear','Unclear'))
    print(df)
    
       ID Match1 Match2 Match3 Match4 Match5  sum_yes    final
    0   1    Yes     No    Yes    Yes    Yes        4    Clear
    1   2    Yes     No    Yes    Yes     No        3  Unclear
    2   2    Yes     No     No    Yes    Yes        3  Unclear
    3   3     No    Yes    Yes    Yes     No        3    Clear
    4   3     No    Yes     No     No     No        1  Unclear
    5   4    Yes     No    Yes     No     No        2  Unclear
    6   4    Yes     No    Yes    Yes    Yes        4    Clear
    

    附笔 你可以放弃 sum_yes 如果你想的话,可以列。

        3
  •  1
  •   Chris    7 年前

    使用 pandas.DataFrame.groupby :

    final_match = []
    for i, d in df.groupby('ID'):
        if len(d) == 1:
            final_match.append('Clear')
        else:
            counter = (d.filter(like='Match') == 'Yes').sum(1)
            if counter.nunique() == 1:
                final_match.extend(['Unclear'] * len(d))
            else:
                final_match.extend(counter.apply(lambda x: 'Clear' if x == max(counter) else 'Unclear').tolist())
    df['final_match'] = final_match
    
    print(df)
       ID Match1 Match2 Match3 Match4 Match5 final_match
    0   1    Yes     No    Yes    Yes    Yes       Clear
    1   2    Yes     No    Yes    Yes     No     Unclear
    2   2    Yes     No     No    Yes    Yes     Unclear
    3   3     No    Yes    Yes    Yes     No       Clear
    4   3     No    Yes     No     No     No     Unclear
    5   4    Yes     No    Yes     No     No     Unclear
    6   4    Yes     No    Yes    Yes    Yes       Clear
    

    说明:

    • len(d) == 1 :如果不重复,则添加 Clear
    • counter = (d.filter(like='Match') == 'Yes').sum(1) :统计每列中“是”的数目
    • counter.nunique() == 1 :如果所有行都有相同的“是”编号,则所有行都标记为“不清楚”
    • counter.apply(lambda x: 'Clear' if x == max(counter) else 'Unclear').tolist() :如果行的“是”计数不同,则用“清除”标记最高行,用“不清楚”标记其余行