python - 如何仅对数据框中的特定行进行排名?

标签 python pandas dataframe

我有一个数据框,其中包含参与某种行为的人数百分比以及总人口的指数。我想按索引对这些行为进行排名...但是我想从该排名中排除发生率非常低的行为。

如果我只是限制整个数据帧以排除这些行为,那么很容易做到,但这里有一个问题——我仍然想将它们包含在我的 df 中;我只是不想将它们纳入排名。

我的数据框是这样开始的,以组作为索引:

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 的所有列。)

它确实有效,但感觉像是一种非常笨拙的方法,我想知道是否有更好、更优雅的方法。有吗?

最佳答案

两种方法

使用df.where:

由于 NA 组会自动排除在 groupby ( see here in docs ) 中,并且 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)

查询当然可以替换为 bool 索引,例如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

关于python - 如何仅对数据框中的特定行进行排名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46505306/

相关文章:

python - 在特定目录的上下文中运行 python unittest

python - Pandas:按包含字典的列中字典的键进行分组

python - 将 pandas 列中除第一个之外的重复数字替换为 NAN 值

python - 插入 DataFrame 列并根据 PySpark 或 Pandas 中的另一列进行排序

dataframe - 从日期时间列中提取学期

python - 在 argparse 中设置互斥集

python - 使用 django 实现一个计算请求的计数器

python - Pandas :从列 A 中提取 B 列不存在的数据

python - HSV 图像阈值化结果与 ImageJ 和 OpenCV 不同

python - 多索引失败