2017-08-31 54 views
2

我需要连接熊猫数据框的2列或更多列中的字符串。将缺失值的熊猫字符串列组合起来

我发现这个answer,它工作正常,如果你没有任何缺失值。不幸的是,我有,而这导致像“ValueA; None”这样的事情,这不是很干净。

示例数据:

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

你尝试使用fillna与col_b一个空字符串 ''? – Quickbeam2k1

+0

刚刚做过,但如果我在第一列中有NaN,我会得到“; val_B”。在这两栏中我都会看到“;” – CoMartel

回答

5

您可以使用applyif-else

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