什么是熊猫系列的分位数函数的倒数?

时间:2014-10-21 14:25:15

标签: python pandas quantile

分位数函数给出了给定的大熊猫系列的分位数 s

E.g。

  

s.quantile(0.9)是4.2

是否存在反函数(即累积分布),它找到值x使得

  

s.quantile(X)= 4

由于

8 个答案:

答案 0 :(得分:44)

我和你一样有同样的问题!我找到了一种使用scipy得到分位数逆的简单方法。

#libs required
from scipy import stats
import pandas as pd
import numpy as np

#generate ramdom data with same seed (to be reproducible)
np.random.seed(seed=1)
df = pd.DataFrame(np.random.uniform(0,1,(10)), columns=['a'])

#quantile function
x = df.quantile(0.5)[0]

#inverse of quantile
stats.percentileofscore(df['a'],x)

答案 1 :(得分:8)

排序可能很昂贵,如果你寻找单个值,我猜你最好用它来计算它:

s = pd.Series(np.random.uniform(size=1000))
( s < 0.7 ).astype(int).mean() # =0.7ish

可能有办法避免使用int(bool)shenanigan。

答案 2 :(得分:5)

我知道没有1-liner,但你可以用scipy实现这个目标:

import pandas as pd
import numpy as np
from scipy.interpolate import interp1d

# set up a sample dataframe
df = pd.DataFrame(np.random.uniform(0,1,(11)), columns=['a'])
# sort it by the desired series and caculate the percentile
sdf = df.sort('a').reset_index()
sdf['b'] = sdf.index / float(len(sdf) - 1)
# setup the interpolator using the value as the index
interp = interp1d(sdf['a'], sdf['b'])

# a is the value, b is the percentile
>>> sdf
    index         a    b
0      10  0.030469  0.0
1       3  0.144445  0.1
2       4  0.304763  0.2
3       1  0.359589  0.3
4       7  0.385524  0.4
5       5  0.538959  0.5
6       8  0.642845  0.6
7       6  0.667710  0.7
8       9  0.733504  0.8
9       2  0.905646  0.9
10      0  0.961936  1.0

现在我们可以看到这两个函数是彼此相反的。

>>> df['a'].quantile(0.57)
0.61167933268395969
>>> interp(0.61167933268395969)
array(0.57)
>>> interp(df['a'].quantile(0.43))
array(0.43)

interp也可以接受列表,numpy数组或pandas数据系列,任何iterator真的!

答案 3 :(得分:4)

刚遇到同样的问题。这是我的两分钱。

def inverse_percentile(arr, num):
    arr = sorted(arr)
    i_arr = [i for i, x in enumerate(arr) if x > num]

    return i_arr[0] / len(arr) if len(i_arr) > 0 else 1

答案 4 :(得分:1)

解决方案 1(当 s 未排序时):

计算 s 中小于 x 的记录数 -- O(n)

# Find the percentile of `x` in `s`
(s<x).sum()/len(s)  # or shortly, (s<x).mean()

Solution-2 (当 s 被排序时): -- O(log(n))

s.searchsorted(x)/len(s)

另见:pandas.Series.searchsorted

答案 5 :(得分:0)

从数学上讲,您试图找到CDF或返回s小于或等于q的值或分位数的概率:

F(q) = Pr[s <= q]

可以使用numpy并尝试以下单行代码:

np.mean(s.to_numpy() <= q)

答案 6 :(得分:0)

您可以使用statsmodels中的ECDF函数。 ECDF代表经验分布函数,“经验”是指它创建的函数是基于数据中观察到的事实。

假设您有一系列s

import pandas as pd
s = pd.Series(np.random.uniform(size=1000))

您可以将CDF评估为0.282:

(s <= 0.282).mean()

或者您可以使用statsmodels函数创建ECDF:

from statsmodels.distributions.empirical_distribution import ECDF

ecdf_s = ECDF(s)

ecdf_s

[ecdf_s(k) for k in [0.282, 0.544, 0.775]]

并检查它是否为分位数的倒数:

s.quantile([0.25, 0.50, 0.75])

答案 7 :(得分:0)

我使用 np.searchsorted 函数来“查找应该插入元素以保持顺序的索引”

np.random.seed(seed=1)

#we want to find the 5th 10-tile of a series of 20 elements
S = 20
N = 10
n = 5

df = pd.DataFrame(np.random.uniform(0,1,S), columns=['a'])

#quantile N function
q = df['a'].quantile(np.arange(0,N+1)/(N))

print(q)

#retrieve the ntile
x = q.iloc[n]

print('-'*30)
print(f"the {n}th {N}-tile of the series is: {x}")

#inverse
print('-'*30)
print(f"{x} is in the {np.searchsorted(q,x)}th {N}-tile of the series")

#and it works also with a value not present in the series
x=x+random.uniform(-.2,.2)
print('-'*30)
print(f"{x} is in the {np.searchsorted(q,x)}th {N}-tile of the series")

输出:

0.0    0.000114
0.1    0.085843
0.2    0.145482
0.3    0.194549
0.4    0.263180
0.5    0.371164
0.6    0.417135
0.7    0.455081
0.8    0.581045
0.9    0.688730
1.0    0.878117
Name: a, dtype: float64
------------------------------
the 5th 10-tile of the series is: 0.37116410063685884
------------------------------
0.37116410063685884 is in the 5th 10-tile of the series
------------------------------
0.27693796519907005 is in the 5th 10-tile of the series