【问题标题】:Groupby and filter based on MAX value of a one column AND CONDITIONALLY topN values of another columnGroupby和过滤基于一列的MAX值和另一列的条件topN值
【发布时间】:2020-02-02 11:34:29
【问题描述】:

我有以下数据:

    individual  groupID  choice     probA     probB
0      9710535        0       0  0.025589  0.008647
1      9710535        2       0  0.036252  0.014684
2      9710535        2       0  0.036252  0.013894
3      9710535        1       0  0.090057  0.030648
4      9710535        1       0  0.090057  0.014804
5      9710535        5       0  0.512675  0.021444
6      9710535        5       0  0.512675  0.020298
7      9710535        5       0  0.512675  0.163837
8      9710535        5       0  0.512675  0.085191
9      9710556        1       1  0.034381  0.796679
10     9710556        1       0  0.034381  0.796679
11     9710556        1       0  0.034381  0.796679
12     9710556        1       0  0.034381  0.157622
13     9710556        1       0  0.034381  0.157622
14     9710556        0       0  0.025589  0.008647

我想根据每个probA 上每个groupID 的最大值过滤每个individual 的数据,对于individual 9710535,这是groupID = 5。但是,如果该组的大小小于5,则就是这种情况(它只有 4 个元素),我还希望根据列 probB 将其他组的行放在顶部(5 - 该组的大小)。

最终结果应如下所示:

  individual  groupID  choice     probA     probB
0     9710535        1       0  0.090057  0.030648
1     9710535        5       0  0.512675  0.021444
2     9710535        5       0  0.512675  0.020298
3     9710535        5       0  0.512675  0.163837
4     9710535        5       0  0.512675  0.085191
5     9710556        1       1  0.034381  0.796679
6     9710556        1       0  0.034381  0.796679
7     9710556        1       0  0.034381  0.796679
8     9710556        1       0  0.034381  0.157622
9     9710556        1       0  0.034381  0.157622

我正在使用此伪代码开发自定义函数方法:

def custom_filter(df, groub_by = 'individual', 
                  condition_column1 = 'probA', 
                  condition_column2 = 'probB',
                  top_count = 5)
    return filtered_df

我将不胜感激!

【问题讨论】:

    标签: python pandas dataframe pandas-groupby


    【解决方案1】:

    我认为您需要首先通过GroupBy.transformmax 提取所有最大行,然后将groupIDboolean indexing 过滤器进行比较:

    mask = df['groupID'].eq(df.groupby('individual')['groupID'].transform('max'))
    df1 = df[mask]
    print (df1)
        individual  groupID  choice     probA     probB
    5      9710535        5       0  0.512675  0.021444
    6      9710535        5       0  0.512675  0.020298
    7      9710535        5       0  0.512675  0.163837
    8      9710535        5       0  0.512675  0.085191
    9      9710556        1       1  0.034381  0.796679
    10     9710556        1       0  0.034381  0.796679
    11     9710556        1       0  0.034381  0.796679
    12     9710556        1       0  0.034381  0.157622
    13     9710556        1       0  0.034381  0.157622
    

    然后用Index.isin过滤掉不匹配的行,用DataFrame.sort_values按2列排序:

    df2 = (df[~df.index.isin(df1.index)]
               .sort_values(['individual','probB'], 
                            ascending=[True, False]))
    print (df2)
        individual  groupID  choice     probA     probB
    3      9710535        1       0  0.090057  0.030648
    4      9710535        1       0  0.090057  0.014804
    1      9710535        2       0  0.036252  0.014684
    2      9710535        2       0  0.036252  0.013894
    0      9710535        0       0  0.025589  0.008647
    14     9710556        0       0  0.025589  0.008647
    

    最后通过concat 连接在一起,通过GroupBy.head 获得前 5 名,最后通过另外 2 列排序:

    df = (pd.concat([df1, df2])
            .groupby('individual').head()
            .sort_values(['individual','groupID']))
    print (df)
        individual  groupID  choice     probA     probB
    3      9710535        1       0  0.090057  0.030648
    5      9710535        5       0  0.512675  0.021444
    6      9710535        5       0  0.512675  0.020298
    7      9710535        5       0  0.512675  0.163837
    8      9710535        5       0  0.512675  0.085191
    9      9710556        1       1  0.034381  0.796679
    10     9710556        1       0  0.034381  0.796679
    11     9710556        1       0  0.034381  0.796679
    12     9710556        1       0  0.034381  0.157622
    13     9710556        1       0  0.034381  0.157622
    

    【讨论】:

    • 感谢您的评论!这不是你第一次在这里回答我的问题。你能解释一下这个操作背后的逻辑吗?我想了解它,以便下次我做类似的事情时我自己做。编辑:我在完成评论之前不小心按下了帖子
    • @EmilMirzayev - 答案已编辑并添加了解释。
    • 您的意思是probA,而不是以下代码中的groupID?因为我现在一头雾水,所以答案和之前的不一样:mask = df['groupID'].eq(df.groupby('individual')['groupID'].transform('max')); df = (pd.concat([df1, df2]) .groupby('individual').head() .sort_values(['individual','groupID']))
    • @EmilMirzayev 抱歉,原始答案是否正常?
    • 是的,它工作正常。但是,这个答案也非常有用,我需要进一步使用第二种方法,看看它会把我带到哪里。非常感谢!
    猜你喜欢
    • 2021-01-18
    • 2016-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-17
    • 1970-01-01
    • 1970-01-01
    • 2022-12-06
    相关资源
    最近更新 更多