如何使用python计算相对于另一列的数据列的百分位数排名

时间:2017-03-31 16:40:21

标签: python pandas quantile percentile

我有两列代表相同数量的数据;一列来自我的训练数据,另一列来自我的验证数据。

我知道如何使用以下方法有效地计算训练数据的百分位数排名:

pandas.DataFrame(training_data).rank(pct = True).values

我的问题是,我如何有效地获得验证数据列 relative 到培训数据列的类似百分位数排名?也就是说,对于验证数据列中的每个值,我如何找到其百分位数相对于训练数据列中所有值的排名?

我试过这样做:

def percentrank(input_data,comparison_data):
    rescaled_data = np.zeros(input_data.size)
    for idx,datum in enumerate(input_data):
        rescaled_data[idx] =scipy.stats.percentileofscore(comparison_data,datum)
    return rescaled_data/100

但是我不确定这是否是正确的,并且最重要的是它非常慢,因为它为for循环中的每个值进行了大量的冗余计算。

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:9)

这是一个解决方案。 对训练数据进行排序。然后在验证数据上使用searchsorted。

import pandas as pd
import numpy as np

# Generate Dummy Data
df_train = pd.DataFrame({'Values': 1000*np.random.rand(15712)})

#Sort Data
df_train = df_train.sort_values('Values')

# Calculating Rank and Rank_Pct for demo purposes 
#but note that it is not needed for the solution
# The ranking of the validation data below does not depend on this
df_train['Rank'] = df_train.rank()
df_train['Rank_Pct']= df_train.Values.rank(pct=True)

# Demonstrate how Rank Percentile is calculated
# This gives the same value as .rank(pct=True)
pct_increment = 1./len(df_train)
df_train['Rank_Pct_Manual'] = df_train.Rank*pct_increment

df_train.head()

       Values  Rank  Rank_Pct  Rank_Pct_Manual
2724  0.006174   1.0  0.000064         0.000064
3582  0.016264   2.0  0.000127         0.000127
5534  0.095691   3.0  0.000191         0.000191
944   0.141442   4.0  0.000255         0.000255
7566  0.161766   5.0  0.000318         0.000318

现在使用searchsorted获取验证数据的Rank_Pct

# Generate Dummy Validation Data
df_validation = pd.DataFrame({'Values': 1000*np.random.rand(1000)})

# Note searchsorted returns array index. 
# In sorted list rank is the same as the array index +1
df_validation['Rank_Pct'] = (1 + df_train.Values.searchsorted(df_validation.Values))*pct_increment

以下是最终df_validation数据帧的前几行:

print df_validation.head()
      Values  Rank_Pct
0  307.378334  0.304290
1  744.247034  0.744208
2  669.223821  0.670825
3  149.797030  0.145621
4  317.742713  0.314218

答案 1 :(得分:1)

对上述优秀解决方案的一个小改进是平均从左侧搜索并从右侧搜索找到的位置:

df_validation['Rank_Pct'] = (0.5 + 0.5*df_train.Values.searchsorted(df_validation.Values, side='left') + 0.5*df_train.Values.searchsorted(df_validation.Values, side='right'))*pct_increment

在值多次出现的情况下,此更改很重要。考虑在[1,2,2,2,4]中搜索2 - 从左边搜索给出1,而从右边搜索给出3.平均两个给出与熊猫相同的百分位数排名.rank(pct = True)例程。