2017-06-08 6 views
1

値を上位n個のカテゴリに限定してクリーンアップする必要があるカテゴリのデータフレームがあります。上位n個のカテゴリにない値は、0(または「その他」)の下に格納する必要があります。トップn値のデータフレームをより効率的に作成する方法 - Python

私は以下のコードを試しました。これは、列の各行をループし、次にデータフレーム内の各列を通って、その位置の値がその列の先頭のn value_countsにあるかどうかを確認します。はいの場合は値を保持し、0に置き換えます。

この実装は技術的には機能しますが、行数が多い場合は実行に時間がかかります。 pandas/numpyでこれを達成するより速い方法は何ですか?

z = pd.DataFrame(np.random.randint(1,4,size=(100000, 4))) 
x=pd.DataFrame()  
n=10 
for j in z: 
    for i in z[j].index:  
     if z.at[i,j] in z[j].value_counts().head(n).index.tolist(): 
      x.at[i,j] = z.at[i,j] 
     else: 
      x.at[i,j]= 0 
print(x) 

答えて

1

私はあなたが交換のためにブールマスクにisinでトップの値についてvalue_countswhereでカスタム関数をループの列にapplyを使用することができると思う:

def f(x): 
    y = x.value_counts().head(n).index 
    return x.where(x.isin(y), 0) 

print (z.apply(f)) 

と同じである何:

print (z.apply(lambda x: x.where(x.isin(x.value_counts().head(n).index), 0))) 

サンプル:

#N =100000 
N = 10 
np.random.seed(123) 
z = pd.DataFrame(np.random.randint(1,4,size=(N, 4))) 
print (z) 
    0 1 2 3 
0 3 2 3 3 
1 1 3 3 2 
2 3 2 3 2 
3 1 2 3 2 
4 1 3 1 2 
5 3 2 1 1 
6 1 1 2 3 
7 1 3 1 1 
8 2 1 2 1 
9 1 1 3 2 

x=pd.DataFrame()  
n=2 
for j in z: 
    for i in z[j].index:  
     if z.at[i,j] in z[j].value_counts().head(n).index.tolist(): 
      x.at[i,j] = z.at[i,j] 
     else: 
      x.at[i,j]= 0 
print(x) 
    0 1 2 3 
0 3.0 2.0 3.0 0.0 
1 1.0 3.0 3.0 2.0 
2 3.0 2.0 3.0 2.0 
3 1.0 2.0 3.0 2.0 
4 1.0 3.0 1.0 2.0 
5 3.0 2.0 1.0 1.0 
6 1.0 0.0 0.0 0.0 
7 1.0 3.0 1.0 1.0 
8 0.0 0.0 0.0 1.0 
9 1.0 0.0 3.0 2.0 

print (z.apply(lambda x: x.where(x.isin(x.value_counts().head(n).index), 0))) 
    0 1 2 3 
0 3 2 3 0 
1 1 3 3 2 
2 3 2 3 2 
3 1 2 3 2 
4 1 3 1 2 
5 3 2 1 1 
6 1 0 0 0 
7 1 3 1 1 
8 0 0 0 1 
9 1 0 3 2 
numpy.where

同様のソリューション:

print (z.apply(lambda x: np.where(x.isin(x.value_counts().head(n).index), x, 0))) 
    0 1 2 3 
0 3 2 3 0 
1 1 3 3 2 
2 3 2 3 2 
3 1 2 3 2 
4 1 3 1 2 
5 3 2 1 1 
6 1 0 0 0 
7 1 3 1 1 
8 0 0 0 1 
9 1 0 3 2 
関連する問題