2016-08-22 13 views
3

私のデータセットに多くの列があります&いくつかの変数で値を変更する必要があります。 I dict in loop for pd.DataFrame

import pandas as pd 
import numpy as np 
df = pd.DataFrame({'one':['a' , 'b']*5, 'two':['c' , 'd']*5, 'three':['a' , 'd']*5}) 

以下

df1 = df[['one', 'two']] 

辞書

map = { 'a' : 'd', 'b' : 'c', 'c' : 'b', 'd' : 'a'} 

とループ

df2=[] 
for i in df1.values: 
    np = [ map[x] for x in i] 
    df2.append(np) 

を選択すると、私は列

0を変更できますか

それは動作しますが、それは非常に長い道のりです。それをもっと短くするには?

+1

['df.replace'](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.replace.html)? – DeepSpace

答えて

2

あなたは列を反復処理Series.map()を使用することができます。

cols = ['one', 'two'] 
mapd = { 'a' : 'd', 'b' : 'c', 'c' : 'b', 'd' : 'a'} 

for col in cols: 
    df[col] = df[col].map(mapd).fillna(df[col]) 


df 
Out: 
    one three two 
0 d  a b 
1 c  d a 
2 d  a b 
3 c  d a 
4 d  a b 
5 c  d a 
6 d  a b 
7 c  d a 
8 d  a b 
9 c  d a 

タイミング:

df = pd.DataFrame({'one':['a' , 'b']*5000000, 
        'two':['c' , 'd']*5000000, 
        'three':['a' , 'd']*5000000}) 

%%timeit 
for col in cols: 
    df[col].map(mapd).fillna(df[col]) 
1 loop, best of 3: 1.71 s per loop 

%%timeit 
for col in cols: 
... colSet = set(df[col].values); 
... colMap = {k:v for k,v in mapd.items() if k in colSet} 
... df.replace(to_replace={col:colMap}) 
1 loop, best of 3: 3.35 s per loop 


%timeit df[cols].stack().map(mapd).unstack() 
1 loop, best of 3: 9.18 s per loop 
2

が唯一の 'A' とコルのための全体マップを渡すと、 'B' の値は、効率的ではありません。最初にどの値がdf colであるかを確認します。次に、ここでのように、唯一の彼らのためにマップ:可能ザッツ

>>> cols = ['one', 'two']; 
>>> map = { 'a' : 'd', 'b' : 'c', 'c' : 'b', 'd' : 'a'}; 

>>> for col in cols: 
... colSet = set(df[col].values); 
... colMap = {k:v for k,v in map.items() if k in colSet}; 
... df.replace(to_replace={col:colMap},inplace=True);#not efficient like rly 
... 
>>> df 
    one three two 
0 d  a b 
1 c  d a 
2 d  a b 
3 c  d a 
4 d  a b 
5 c  d a 
6 d  a b 
7 c  d a 
8 d  a b 
9 c  d a 
>>> 
#OR 
In [12]: %%timeit 
...: for col in cols: 
...: colSet = set(df[col].values); 
...: colMap = {k:v for k,v in map.items() if k in colSet}; 
...: df[col].map(colMap) 
...: 
...: 
1 loop, best of 3: 1.93 s per loop 
#OR WHEN INPLACE 
In [8]: %%timeit 
    ...: for col in cols: 
    ...: colSet = set(df[col].values); 
    ...: colMap = {k:v for k,v in map.items() if k in colSet}; 
    ...: df[col]=df[col].map(colMap) 
    ...: 
    ...: 
1 loop, best of 3: 2.18 s per loop 

を過ぎる:

df = pd.DataFrame({'one':['a' , 'b']*5, 'two':['c' , 'd']*5, 'three':['a' , 'd']*5}) 
map = { 'a' : 'd', 'b' : 'c', 'c' : 'b', 'd' : 'a'} 
cols = ['one','two'] 

def func(s): 
    if s.name in cols: 
     s=s.map(map) 
    return s 

print df.apply(func) 

はまた、キー(すなわちの重複を見てあなたは、並列に変更したい場合はBとBにに言うことができます。 Cが、好きではない、A-> B-> C)...

>>> cols = ['one', 'two']; 
>>> map = { 'a' : 'd', 'b' : 'c', 'c' : 'b', 'd' : 'a'}; 
>>> mapCols = {k:map for k in cols}; 
>>> df.replace(to_replace=mapCols,inplace=True); 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "Q:\Miniconda3\envs\py27a\lib\site-packages\pandas\core\generic.py", line 3352, in replace 
    raise ValueError("Replacement not allowed with " 
ValueError: Replacement not allowed with overlapping keys and values 
+0

これは*非効率的*よりも2倍遅いです。 – ayhan

+0

...リリーチェックはしていませんが(論理的には間違ってはいけませんが、私の実装はあまり速くないかもしれません。それは効率的でないこのdf.replaceですか? –

+0

置換は一般的に遅いです(DataFrame全体に一度に適用する場合でも、マップを含む列をループする場合でも)。マップははるかに限定的であり、限定されているためです。違いはあなたの実装から来ているとは思わない。実際、 'Series.map()'の実際の実装は、存在しないキーを経る時間を無駄にしていると思いましたか? – ayhan

1
df = pd.DataFrame({'one':['a' , 'b']*5, 'two':['c' , 'd']*5, 'three':['a' , 'd']*5}) 
m = { 'a' : 'd', 'b' : 'c', 'c' : 'b', 'd' : 'a'} 

cols = ['one', 'two'] 
df[cols] = df[cols].stack().map(m).unstack() 
df 

enter image description here