Python通过列值大于或等于每个子组中的中位数来查找数据框中的记录

时间:2015-03-30 13:50:11

标签: python pandas group-by dataframe

假设我有一个可以通过以下方式启动的数据框:

df = pd.DataFrame({'group1': ['1','2','3','4','5','6'],
                   'group2': ['c','c','d','d','d','e'],
                   'value1': [1.1,2,3,4,5,6],
                   'value2': [7.1,8,9,10,11,12]
                   })
df = df.set_index(['group1', 'group2'])

我希望通过df列对value2进行分组,其值大于或等于索引group2指定的每个子组的中位数。在此示例中,group1中的['2','4','5','6']行应保留在结果中。有人可以帮忙吗?

2 个答案:

答案 0 :(得分:1)

这应该有效:

df['value2'] = df['value2'].groupby(level='group2').transform(lambda x: np.where(x>=np.median(x), x, np.NaN))
df = df.dropna()

它的作用是获取value2列,并按group2将其拆分为组。对于每个组,它会找到中位数,然后使用NaN替换中位数以下的值。然后将其放回value2列,然后删除所有NaN个值的行。

作为替代方案,这里有一个稍微不那么明确的单线:

df = df.groupby(level='group2').transform(lambda x: x if x.name != 'group2' else np.where(x>=np.median(x), x, np.NaN)).dropna()

这大致相同,除了它在两列上运行,但不对group1列做任何事情。

请注意,在第二种方法中,您可以将其存储到第二个变量,例如df2,而不更改原始df(如果您愿意)。你可以用第一种方法做到这一点,但这需要另一行来制作副本。对于这种情况,这个版本要简单得多。

答案 1 :(得分:0)

我认为你需要在设置索引之前进行groupby和比较:

df = pd.DataFrame({'group1': ['1','2','3','4','5','6'],
                   'group2': ['c','c','d','d','d','e'],
                   'value1': [1.1,2,3,4,5,6],
                   'value2': [7.1,8,9,10,11,12]
                   })
gb = df.groupby('group2').value2.median()
df.join(gb, on='group2', rsuffix='_median')
df_filtered = df[df.value2 >= df.join(gb, on='group2', rsuffix='_median').value2_median]
df_filtered.set_index(['group1', 'group2'], inplace=True)
>>> df_filtered 
               value1  value2
group1 group2                
2      c            2       8
4      d            4      10
5      d            5      11
6      e            6      12