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



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

我知道如何有效地计算训练数据的百分位排名:

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

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

我试过这样做:

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 循环中的每个值进行了大量冗余计算。

任何帮助将不胜感激!

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

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

现在使用搜索排序来获取验证数据的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
<</div> div class="one_answers">

对上面不错的解决方案的一个小改进是通过从左侧搜索和从右侧搜索来平均找到的位置:

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(例程相同的百分位排名。

派对迟到了,但这里有一个简洁的解决方案

from scipy import stats
training = pd.Series([64,63,67,69,67])
test = pd.Series([66,72])
training_percentiles = training.rank(pct=True) * 100
testing_percentiles = test.apply(lambda x: stats.percentileofscore(training, x))

training_percentiles:

0     40.0
1     20.0
2     70.0
3    100.0
4     70.0

testing_percentiles:

0     40.0
1    100.0

我已经用系列完成了此操作,但同样可以应用于数据帧

最新更新