【问题标题】:Combine pandas string columns with missing values将 pandas 字符串列与缺失值组合
【发布时间】:2017-08-31 08:18:21
【问题描述】:

我需要在 pandas 数据框的 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

【问题讨论】:

  • 您是否尝试过在 col_b 上使用带有空字符串 '' 的 fillna?
  • 刚刚做了,但如果我在第一列中有 NaN,我会得到“;val_B”。在两列中都有 Nan,我只得到“;”

标签: python pandas


【解决方案1】:

您可以将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

【讨论】:

  • 一个令人惊讶的难题的好答案。 .join().cat() 都出人意料地失败了
  • 我不知道为什么,但我找到的所有解决方案,包括顶级解决方案总是给我一个分隔符,比如“;”,如果 col_B 为空。 “更快”的解决方案是我发现用分隔符连接值并在第二列中处理 np.nans 的唯一方法。再次感谢 Jazrael 先生!
猜你喜欢
  • 2014-07-19
  • 1970-01-01
  • 2018-04-30
  • 2020-06-17
  • 2014-07-05
  • 1970-01-01
  • 2019-01-27
  • 1970-01-01
  • 2015-03-07
相关资源
最近更新 更多