消除给定百分位数以上的所有数据

72

我有一个名为data的pandas DataFrame,其中有一列名为ms。我想消除所有data.ms高于95%分位数的行。目前,我正在执行以下操作:

limit = data.ms.describe(90)['95%']
valid_data = data[data['ms'] < limit]

这个方法是有效的,但我希望将其推广到任何百分位数。最好的方法是什么?

3个回答

120

使用 Series.quantile() 方法:

In [48]: cols = list('abc')

In [49]: df = DataFrame(randn(10, len(cols)), columns=cols)

In [50]: df.a.quantile(0.95)
Out[50]: 1.5776961953820687

要筛选出dfdf.a大于或等于95百分位数的行,请执行以下操作:

In [72]: df[df.a < df.a.quantile(.95)]
Out[72]:
       a      b      c
0 -1.044 -0.247 -1.149
2  0.395  0.591  0.764
3 -0.564 -2.059  0.232
4 -0.707 -0.736 -1.345
5  0.978 -0.099  0.521
6 -0.974  0.272 -0.649
7  1.228  0.619 -0.849
8 -0.170  0.458 -0.515
9  1.465  1.019  0.966

使用pandas,如果我想要比较不同列与特定分位数,是否有类似于numpy广播的快速方法? - Pengju Zhao
1
当删除所有列时,即df[df < df.quantile(.95)]是否也有效?如果不在范围内,则预计所有值都将被过滤掉,并在需要时替换为NaN - Mattia Paterna
基本上相同但更简洁:df.query('a < a.quantile(.95)')。 如果列名很长,可以提高可读性: col = 'some_verbose_metric_name'; df.query(f'{col} < {col}.quantile(.95)') - ribitskiyb

51

在这种情况下,numpy比Pandas快得多:

numpy.percentile(df.a,95) # attention : the percentile is given in percent (5 = 5%)

等价于但比原来快3倍:

df.a.quantile(.95)  # as you already noticed here it is ".95" not "95"

因此,针对您的代码,它给出:

df[df.a < np.percentile(df.a,95)]

3
可以确认,如果您能承担列提取成本,numpy的实现要快得多。 - deepelement
@2diabolos.com 有没有一种方法可以在多个 Pandas 列上实现百分位数过滤器。 - Furqan Hashim
类似于 df[numpy.logical_and(df.a < np.percentile(df.a,95),df.b < np.percentile(df.b,95))] 这样的东西?还是你想提一个新问题? - 2diabolos.com
1
@deepelement,列提取成本有哪些权衡? - Fred Zimmerman

7

您可以使用query来获得更简洁的选项:

df.query('ms < ms.quantile(.95)')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接