【问题标题】:Getting corresponding values in a groupby获取groupby中的对应值
【发布时间】:2020-09-01 13:52:17
【问题描述】:

我有一个类似的数据集

Serial    A        B       
1         12               
1         31
1
1         12
1         31       203
1         10    
1         2
2         32       100     
2         32       242
2         3
3         2                
3         23       100     
3
3         23

我根据 Serial 对数据帧进行分组,并通过df['A_MAX'] = df.groupby('Serial')['A'].transform('max').values 找到每个A 列的最大值,并通过df['A_MAX'] = df['A_MAX'].mask(df['Serial'].duplicated(), '') 保留第一个值

Serial    A        B       A_MAX    B_corresponding
1         12               31       203
1         31
1
1         12
1         31       203
1         10    
1         2
2         32       100     32       100
2         32       242
2         3
3         2                23       100
3         23       100     
3
3         23

现在对于B_corresponding 列,我想获取A_MAX 对应的B 值。我想在A 中找到A_MAX 值,但每组有类似的最大值A 值。附加条件,例如在Serial 2 中,我还希望获得32 之间的最小B

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    想法是使用DataFrame.sort_values 获取每个组的最大值,然后通过DataFrame.dropna 删除缺失值并通过Serial 通过DataFrame.drop_duplicates 获取第一行。通过DataFrame.set_index 创建Series 并最后使用Series.map

    df['A_MAX'] = df.groupby('Serial')['A'].transform('max')
    df['A_MAX'] = df['A_MAX'].mask(df['Serial'].duplicated())
    
    s = (df.sort_values(['Serial','A'], ascending=[True, False])
           .dropna(subset=['B'])
           .drop_duplicates('Serial')
           .set_index('Serial')['B'])
    df['B_corresponding'] = df['Serial'].map(s).mask(df['Serial'].duplicated())
    print (df)
        Serial     A      B  A_MAX  B_corresponding
    0        1  12.0    NaN   31.0            203.0
    1        1  31.0    NaN    NaN              NaN
    2        1   NaN    NaN    NaN              NaN
    3        1  12.0    NaN    NaN              NaN
    4        1  31.0  203.0    NaN              NaN
    5        1  10.0    NaN    NaN              NaN
    6        1   2.0    NaN    NaN              NaN
    7        2  32.0  100.0   32.0            100.0
    8        2  32.0  242.0    NaN              NaN
    9        2   3.0    NaN    NaN              NaN
    10       3   2.0    NaN   23.0            100.0
    11       3  23.0  100.0    NaN              NaN
    12       3   NaN    NaN    NaN              NaN
    13       3  23.0    NaN    NaN              NaN
    

    将缺失值转换为空字符串是可能的,但是得到混合值 - 数字和字符串,所以接下来的处理应该是有问题的:

    df['A_MAX'] = df.groupby('Serial')['A'].transform('max')
    df['A_MAX'] = df['A_MAX'].mask(df['Serial'].duplicated(), '')
    
    s = (df.sort_values(['Serial','A'], ascending=[True, False])
           .dropna(subset=['B'])
           .drop_duplicates('Serial')
           .set_index('Serial')['B'])
    
    df['B_corresponding'] = df['Serial'].map(s).mask(df['Serial'].duplicated(), '')
    print (df)
        Serial     A      B A_MAX B_corresponding
    0        1  12.0    NaN    31             203
    1        1  31.0    NaN                      
    2        1   NaN    NaN                      
    3        1  12.0    NaN                      
    4        1  31.0  203.0                      
    5        1  10.0    NaN                      
    6        1   2.0    NaN                      
    7        2  32.0  100.0    32             100
    8        2  32.0  242.0                      
    9        2   3.0    NaN                      
    10       3   2.0    NaN    23             100
    11       3  23.0  100.0                      
    12       3   NaN    NaN                      
    13       3  23.0    NaN                      
    

    【讨论】:

      【解决方案2】:

      如果您不那么倾向于只使用 pandas,您也可以使用字典来达到同样的效果。

      a_to_b_mapping = df.groupby('A')['B'].min().to_dict()
      series_to_a_mapping = df.groupby('Series')['A'].max().to_dict()
      agg_df = {}
      for series, a in series_to_a_mapping.items():
          agg_df.append((series, a, a_to_b_mapping.get(a, None)))
        
      agg_df = pd.DataFrame(agg_df, columns=['Series', 'A_max', 'B_corresponding'])
      agg_df.head()
      
          Series  A_max   B_corresponding
      0   1   31.0    203.0
      1   2   32.0    100.0
      2   3   23.0    100.0
      

      如果需要,您可以将其加入原始数据框并屏蔽重复项。

      dft = df.join(final_df.set_index('Serial'), on='Serial', how='left')
      dft['A_max'] = dft['A_max'].mask(dft['A_max'].duplicated(), '')
      dft['B_corresponding'] = dft['B_corresponding'].mask(dft['B_corresponding'].duplicated(), '')
      dft
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-01-25
        • 2019-06-06
        • 2013-02-06
        • 1970-01-01
        • 1970-01-01
        • 2020-01-30
        • 2021-08-26
        • 1970-01-01
        相关资源
        最近更新 更多