同じ量を表す2列のデータがあります。 1つの列はトレーニングデータからのもので、もう1つは検証データからのものです。
以下を使用して、トレーニングデータのパーセンタイルランキングを効率的に計算する方法を知っています。
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
上記のNiceソリューションの小さな改善点は、左から検索して右から検索することで見つかった位置を平均化することです。
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になります。2つを平均すると、pandasと同じパーセンタイルランクになります。 pct = True)ルーチン。