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

Doo*_*les 4 python percentile quantile pandas

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

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

pandas.DataFrame(training_data).rank(pct = True).values
Run Code Online (Sandbox Code Playgroud)

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

我试过这样做:

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
Run Code Online (Sandbox Code Playgroud)

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

任何帮助将不胜感激!

小智 11

这是一个解决方案.对训练数据进行排序.然后在验证数据上使用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
Run Code Online (Sandbox Code Playgroud)

现在使用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
Run Code Online (Sandbox Code Playgroud)

以下是最终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
Run Code Online (Sandbox Code Playgroud)


小智 5

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

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
Run Code Online (Sandbox Code Playgroud)

在某个值多次出现的情况下,此更改很重要。考虑在 [1,2,2,2,4] 中搜索 2 - 从左侧搜索给出 1,而从右侧搜索给出 3。对两者求平均给出与 pandas .rank(pct=True) 相同的百分位排名常规。