假设我有一个可以通过以下方式启动的数据框:
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']
行应保留在结果中。有人可以帮忙吗?
答案 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