我有一个数据框,其中包含参与行为的人员百分比,以及一般人群的索引。我想按索引对这些行为进行排名...... 但我想从此排名中排除非常低的发生率行为。
如果我只是限制整个数据框以排除这些行为,那么很容易做到,但这里有捕获 - 我仍然希望将它们包含在我的df中;我只是不想把它们列入排名。
我的数据框是这样开始的,以group为索引:
GROUP BEHAVIOR SUBBEHAVIOR PERCENT INDEX
GROUP1 behavior1 foo 0.521 123
GROUP1 behavior2 bar 0.013 213
GROUP1 behavior2 fuzz 1.034 103
GROUP1 behavior3 foobar 0.750 131
GROUP2 behavior1 foo 1.521 101
GROUP2 behavior2 bar 0.913 91
GROUP2 behavior2 fuzz 0.034 301
GROUP2 behavior3 foobar 0.950 87
但是,我不想要第二排0.013排名。我想改为:
GROUP BEHAVIOR SUBBEHAVIOR PERCENT INDEX RANK
GROUP1 behavior1 foo 0.521 123 2
GROUP1 behavior2 bar 0.013 213 NaN
GROUP1 behavior2 fuzz 1.034 103 3
GROUP1 behavior3 foobar 0.750 131 1
GROUP2 behavior1 foo 1.521 101 1
GROUP2 behavior2 bar 0.913 91 2
GROUP2 behavior2 fuzz 0.034 301 NaN
GROUP2 behavior3 foobar 0.950 87 3
我通过这样做实现了上述目标:
filtered = df[fd.loc[:,'PERCENT']>0.05].copy()
filtered['RANK'] = filtered.groupby(level=0).rank(ascending=False)['INDEX']
final = df.merge(filtered, on=df.columns.tolist(), how='left')
(我有更多的专栏使子行为真正独特,因此为什么我已经通过了所有df的列。)
它有效,但感觉就像一种非常混乱的方法,我想知道是否有更好,更优雅的方式。有吗?
答案 0 :(得分:3)
使用df.where
:
由于在groupby
see here in docs)中自动排除了NA组,而rank
的默认NA处理只是保留原样,您可以使用df.where
为您的过滤器,直接进行。
df['RANK'] = (df.where(df.PERCENT > .05)
.groupby('GROUP')
.rank(ascending=False)
.INDEX)
>>> df
BEHAVIOR INDEX PERCENT SUBBEHAVIOR RANK
GROUP
GROUP1 behavior1 123 0.521 foo 2.0
GROUP1 behavior2 213 0.013 bar NaN
GROUP1 behavior2 103 1.034 fuzz 3.0
GROUP1 behavior3 131 0.750 foobar 1.0
GROUP2 behavior1 101 1.521 foo 1.0
GROUP2 behavior2 91 0.913 bar 2.0
GROUP2 behavior2 301 0.034 fuzz NaN
GROUP2 behavior3 87 0.950 foobar 3.0
直截了当的解决方案:
或者,只需先重置DataFrame上的索引,这样就可以使用标识符来对齐索引。
df.reset_index(inplace=True)
df['RANK'] = (df.query('PERCENT > .05') # or using a mask ofc
.groupby('GROUP')
.rank(ascending=False)
.INDEX)
query
当然可以用类似df[df.PERCENT > .05]
的布尔索引替换。
那么
>>> df.set_index('GROUP')
BEHAVIOR SUBBEHAVIOR PERCENT INDEX RANK
GROUP
GROUP1 behavior1 foo 0.521 123 2.0
GROUP1 behavior2 bar 0.013 213 NaN
GROUP1 behavior2 fuzz 1.034 103 3.0
GROUP1 behavior3 foobar 0.750 131 1.0
GROUP2 behavior1 foo 1.521 101 1.0
GROUP2 behavior2 bar 0.913 91 2.0
GROUP2 behavior2 fuzz 0.034 301 NaN
GROUP2 behavior3 foobar 0.950 87 3.0
答案 1 :(得分:0)
df.join(df.loc[df['PERCENT']>0.05].groupby('GROUP')['INDEX'].rank(ascending=False).rename('RANK'))
如果在运行计算之前创建空白列,也可以使用.map()+ .insert()或.update()。