2017-03-12 21 views
1

num列の値を置き換えようとしています。 abの各文字については、私は辞書を持っています。私は、最後の行の割り当てが正常に動作のみ2 forループ内のdataframe.replace()

(& B)下記
data = pd.DataFrame({'ab' : ['A','B','A','A','B'], 'num' : ['01','02','01','01','01']}) 

a_replacements = { 'num' : { '01' : 'funny', '02' : 'serious' }} 
b_replacements = { 'num' : { '01' : 'beginning', '02' : 'end' }} 

data[data.ab == 'A'] = data[data.ab == 'A'].replace(inplace=True, to_replace=a_replacements) 

を示しました。

for letter in data.ab.unique(): 
    data.loc[data.ab == letter] = data.replace(to_replace=letter.lower()+"_replacements") 

は、私が取得するには:


私は abで26異なる文字のために numに置き換えた値に持つループのためのこの内部を使用しようとする。しかし、私は、次の問題に直面しています
TypeError         Traceback (most recent call last) 
<ipython-input-96-acd3197ceef4> in <module>() 
     1 for letter in data.ab.unique(): 
     2  print(letter.lower()+"_replacements") 
----> 3  data.loc[data.ab == letter] = data.replace(to_replace=letter.lower()+"_replacements") 

/Users/alokshenoy/.pyenv/versions/miniconda3-latest/lib/python3.6/site-packages/pandas/core/generic.py in replace(self, to_replace, value, inplace, limit, regex, method, axis) 
    3427    if isinstance(to_replace, (tuple, list)): 
    3428     return _single_replace(self, to_replace, method, inplace, 
-> 3429          limit) 
    3430 
    3431    if not is_dict_like(to_replace): 

/Users/alokshenoy/.pyenv/versions/miniconda3-latest/lib/python3.6/site-packages/pandas/core/generic.py in _single_replace(self, to_replace, method, inplace, limit) 
    70  if self.ndim != 1: 
    71   raise TypeError('cannot replace {0} with method {1} on a {2}' 
---> 72       .format(to_replace, method, type(self).__name__)) 
    73 
    74  orig_dtype = self.dtype 

TypeError: cannot replace ['a_replacements'] with method pad on a DataFrame 

これを解決する方法はありますか?

+1

あなたは、単に辞書の名前に対応する文字列を渡していますマッピングを生成するために使用します。代わりに、 'dict'オブジェクトに属しているこれらの式が正しく推論されるように、' replace'演算中に書式化された文字列に 'eval'を直接使用してください。' data.replace(to_replace = eval(letter.lower()+ "_replacements" )) ' –

+0

これは私が直面している問題に直接対処しています!ありがとうございました。 –

答えて

1

問題の解決方法はgroupbyです。これにより、一意の置換を使用する各グループを処理できます。

キーコード:

for name, group in data.groupby(['ab']): 
    data[data.ab == name] = group.replace(to_replace=replacements[name]) 

すべてのコード:

import pandas as pd 

data = pd.DataFrame({'ab': ['A', 'B', 'A', 'A', 'B'], 
        'num': ['01', '02', '01', '01', '01']}) 
print(data) 

replacements = dict(
    A={'num': {'01': 'funny', '02': 'serious'}}, 
    B={'num': {'01': 'beginning', '02': 'end'}}, 
) 

for name, group in data.groupby(['ab']): 
    data[data.ab == name] = group.replace(to_replace=replacements[name]) 

print(data) 

結果:

ab num 
0 A 01 
1 B 02 
2 A 01 
3 A 01 
4 B 01 

    ab  num 
0 A  funny 
1 B  end 
2 A  funny 
3 A  funny 
4 B beginning 
+0

Brilliant! 'groupby'を考えなかった! –

1

あなたはを使用することができますdictsのリストに列abzipによって作成されたすべてのdictsの辞書で名前のどのマップリストを置き換えるためapplyと:今

a_replacements = { 'num' : { '01' : 'funny', '02' : 'serious' }} 
b_replacements = { 'num' : { '01' : 'beginning', '02' : 'end' }} 
abnames = ['A','B'] 
L = [a_replacements, b_replacements] 

replacements = dict(zip(abnames, L)) 
print (replacements) 
{'A': {'num': {'01': 'funny', '02': 'serious'}}, 
'B': {'num': {'01': 'beginning', '02': 'end'}}} 

df = data.groupby('ab').apply(lambda x: x.replace(replacements[x.name])) 
print (df) 
    ab  num 
0 A  funny 
1 B  end 
2 A  funny 
3 A  funny 
4 B beginning 
+0

私の質問に答えていただきありがとうございます。私は答えとしてあなたの前に提出されたものに印をつけました。それにもかかわらず、あなたのソリューションは効果的に機能します! –