2016-05-21 17 views
2

複数の列を持つ2つのデータフレームがあります。条件に基づいて1台のパンダのデータフレームを別のものに置き換えます

df_1 = pd.DataFrame({'A': ['x', '-', 'z'], 'B': [1, 6, 9], 'C': [2, 1, '-']}) 
> df_1 

    A B C 
0 x 1 2 
1 - 6 1 
2 z 9 - 

df_2 = pd.DataFrame({'A': ['w', 'y', 'y'], 'B': [5, 6, 9], 'C': [2, 1, 8]}) 
> df_2 

    A B C 
0 w 5 2 
1 y 6 1 
2 y 9 8 

条件(論理マスク)に基づいて、あるデータフレームの値を別のデータフレームの値に置き換えるにはどうすればよいですか?ここで 、欠損値は'-'として注目され、私は結果を得るために、代わりにdf_2からの値を使用したい:

> df 
    A B C 
0 x 1 2 
1 y 6 1 
2 z 9 8 
+1

ご期待手順としてくださいつながります? – su79eu7k

+1

ありがとう、私はそれを追加していないことに気付かなかった –

答えて

4

IIUCあなたはastypeによってstringに値を変換してboolean maskを作成し、-と比較することができます。コメントで

mask = df_1.astype(str) == '-' 
print (mask) 
     A  B  C 
0 False False False 
1 True False False 
2 False False True 

print (df_1.mask(mask, df_2)) 
    A B C 
0 x 1 2 
1 y 6 1 
2 z 9 8 

print (df_1.where(~mask, df_2)) 
    A B C 
0 x 1 2 
1 y 6 1 
2 z 9 8 

EDIT:最終mask~によってを反転してmaskまたはwhereDataFrameから-に値を埋める

一つの可能​​な解決策は、su79eu7kである、あなたに感謝:

masks = [('A', r'[a-zA-Z]'), ('B', r'\d'), ('C', r'\d')]; 
print pd.concat([~(df_1[col].astype(str).str.contains(regex)) for col, regex in masks], axis=1) 

別の解決方法を作成mask - 最初fillna可能NaNの値がある場合、replaceの値がdictからNaNまでであり、最後にisnullという値が見つかりませんでした。

import pandas as pd 
import numpy as np 

df_1 = pd.DataFrame({'A': ['-x', '-', np.nan],'B': [1, 6, 'Unknown'],'C': [2, 1, 'Missing']}) 
print (df_1) 

df_2 = pd.DataFrame({'A': ['w', 'y', 'y'], 'B': [5, 6, 9], 'C': [2, 1, 8]}) 
print (df_2) 

mask_li = ['-','Unknown','Missing'] 
d = {x:np.nan for x in mask_li} 

mask = df_1.fillna(1).replace(d).isnull() 
print (mask) 
     A  B  C 
0 False False False 
1 True False False 
2 False True True 

print (df_1.mask(mask, df_2))  
    A B C 
0 -x 1 2 
1 y 6 1 
2 NaN 9 8 

あなたはstr.containsを使用することができますが、他のデータがリストmask_liから値を含めることはできません。

mask_li = ['-','Unknown','Missing']  

mask= df_1.copy() 
for col in df_1.columns: 
    mask[col] = mask[col].astype(str).str.contains('|'.join(mask_li)) 

print (mask) 
     A  B  C 
0 False False False 
1 True False False 
2 False True True 

print (df_1.mask(mask, df_2))  
    A B C 
0 x 1 2 
1 y 6 1 
2 z 9 8 

しかし、別のデータがmask_li例えばからの値が含まれている場合、問題がある可能性があります-

例えば:

import pandas as pd 
import numpy as np 

df_1 = pd.DataFrame({'A': ['-x', '-', '-z'], 'B': [1, 6, 'Unknown'], 'C': [2, 1, 'Missing']}) 
print (df_1) 

df_2 = pd.DataFrame({'A': ['w', 'y', 'y'], 'B': [5, 6, 9], 'C': [2, 1, 8]}) 
print (df_2) 

mask_li = ['-','Unknown','Missing']  

mask= df_1.copy() 
for col in df_1.columns: 
    mask[col] = mask[col].astype(str).str.contains('|'.join(mask_li)) 

print (mask) 
     A  B  C 
0 True False False 
1 True False False 
2 True True True 

print (df_1.mask(mask, df_2))  
    A B C 
0 w 1 2 
1 y 6 1 
2 y 9 8 

一つの可能​​な解決策:

import pandas as pd 
import numpy as np 

df_1 = pd.DataFrame({'A': ['-x', '-', '-z'], 'B': [1, 6, 'Unknown'], 'C': [2, 1, 'Missing']}) 
print (df_1) 

df_2 = pd.DataFrame({'A': ['w', 'y', 'y'], 'B': [5, 6, 9], 'C': [2, 1, 8]}) 
print (df_2) 

mask_li = ['Unknown','Missing']  

mask= df_1.copy() 
for col in df_1.columns: 
    column = mask[col].astype(str) 
    mask[col] = (column.str.contains('|'.join(mask_li))) | (column == '-') 

print (mask) 
     A  B  C 
0 False False False 
1 True False False 
2 False True True 

print (df_1.mask(mask, df_2))  
    A B C 
0 -x 1 2 
1 y 6 1 
2 -z 9 8 
+0

ありがとう! '' -''、 '' Missed''、 '' Unknown''などのようないくつかの欠損値がある場合、どうすればいいか教えてください。 –

+0

'mask = (df_1.astype(str)== ' - ')| (df_1.astype(str)== 'Missed') 'ですが、欠落値のリストが長すぎる場合は適切ではありません。 –

+1

@KatrinaMalakhova次に、 'mask '= [(' A '、r' [a-zA-Z] ')、(' B '、r' \ d ')、(' C '、r' \ d ')];マスクの正規表現]、軸= 1) '列' A 'の非アルファベットをフィルタリングするpd.concat([〜(df_1 [col] .astype(str).str.contains(regex)))列「B」と「C」に数字を記入してください。 – su79eu7k

関連する問題