2017-08-31 20 views
2

pandasデータフレームの2つ以上の列に文字列を連結する必要があります。欠損値を含むpandas文字列を組み合わせる

見つけたanswerは、欠損値がなければ正常に動作します。残念なことに、私は持っている、これは本当にきれいではない "ValueA;なし"のようなものにつながる。

例データ:

col_A | col_B 
------ | ------ 
val_A | val_B 
None | val_B 
val_A | None 
None | None 

私はこの結果を必要とする:

col_merge 
--------- 
val_A;val_B 
val_B 
val_A 
None 
+2

あなたはcol_bに空の文字列 '' でfillna使用してみましたか? – Quickbeam2k1

+0

ただしましたが、最初の列にNaNがある場合は、「; val_B」を取得します。両方の列にナンと私はちょうど得る ";" – CoMartel

答えて

5

あなたはif-elseapplyを使用することができます。

df = df.apply(lambda x: None if x.isnull().all() else ';'.join(x.dropna()), axis=1) 
print (df) 
0 val_A;val_B 
1   val_B 
2   val_A 
3   None 
dtype: object 

速く解決のためには、可能な使用である:

#add separator and replace NaN to empty space 
#convert to lists 
arr = df.add('; ').fillna('').values.tolist() 
#list comprehension, replace empty spaces to NaN 
s = pd.Series([''.join(x).strip('; ') for x in arr]).replace('^$', np.nan, regex=True) 
#replace NaN to None 
s = s.where(s.notnull(), None) 
print (s) 
0 val_A;val_B 
1   val_B 
2   val_A 
3   None 
dtype: object 

#40000 rows 
df = pd.concat([df]*10000).reset_index(drop=True) 

In [70]: %%timeit 
    ...: arr = df.add('; ').fillna('').values.tolist() 
    ...: s = pd.Series([''.join(x).strip('; ') for x in arr]).replace('^$', np.nan, regex=True) 
    ...: s.where(s.notnull(), None) 
    ...: 
10 loops, best of 3: 74 ms per loop 


In [71]: %%timeit 
    ...: df.apply(lambda x: None if x.isnull().all() else ';'.join(x.dropna()), axis=1) 
    ...: 
1 loop, best of 3: 12.7 s per loop 

#another solution, but slowier a bit 
In [72]: %%timeit 
    ...: arr = df.add('; ').fillna('').values 
    ...: s = [''.join(x).strip('; ') for x in arr] 
    ...: pd.Series([y if y != '' else None for y in s]) 
    ...: 
    ...: 
10 loops, best of 3: 119 ms per loop 
+0

うまく動作します、ありがとう! – CoMartel

+0

幸いです、幸運を助けることができます! – jezrael

関連する問題