如何使用 python 计算一列数据相对于另一列的百分位数排名
How to calculate a percentile ranking of a column of data relative to another column using 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 循环中的每个值进行了大量冗余计算。
如有任何帮助,我们将不胜感激!
这是一个解决方案。
对训练数据进行排序。然后对验证数据使用 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
上述解决方案的一个小改进是对从左侧搜索和从右侧搜索找到的位置进行平均:
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。对两者求平均得到与 pandas 相同的百分位数排名。排名( pct=True) 例程。
我有两列数据代表相同的数量;一列来自我的训练数据,另一列来自我的验证数据。
我知道如何有效地计算训练数据的百分位数排名:
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 循环中的每个值进行了大量冗余计算。
如有任何帮助,我们将不胜感激!
这是一个解决方案。 对训练数据进行排序。然后对验证数据使用 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
上述解决方案的一个小改进是对从左侧搜索和从右侧搜索找到的位置进行平均:
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。对两者求平均得到与 pandas 相同的百分位数排名。排名( pct=True) 例程。