使用Pandas Python将单元格合并为带分隔符的字符串

11

鉴于以下内容:

df = pd.DataFrame({'col1' : ["a","b"],
            'col2'  : ["ab",np.nan], 'col3' : ["w","e"]})
我希望能够创建一个列,将三个列的内容连接成一个字符串,用字符“*”分隔,同时忽略NaN
所以我会得到类似于以下的东西:
a*ab*w
b*e

有什么想法吗?

刚刚意识到还有一些额外的要求,我需要这个方法可以处理整数和浮点数,并且能够处理特殊字符(例如,西班牙字母)。


我用以下代码测试了我的答案:df = pd.DataFrame({'col1' : ["a","b",3,'ñ'], 'col2' : ["ab",np.nan, 4,'ñ'], 'col3' : ["w","e", 6,'ñ']}),并且它仍然有效。 - EdChum
6个回答

15
In [68]:

df['new_col'] = df.apply(lambda x: '*'.join(x.dropna().values.tolist()), axis=1)
df
Out[68]:
  col1 col2 col3 new_col
0    a   ab    w  a*ab*w
1    b  NaN    e     b*e

更新

如果您有整数或浮点数,您可以首先将它们转换为str

In [74]:

df = pd.DataFrame({'col1' : ["a","b",3],
            'col2'  : ["ab",np.nan, 4], 'col3' : ["w","e", 6]})
df
Out[74]:
  col1 col2 col3
0    a   ab    w
1    b  NaN    e
2    3    4    6
In [76]:

df['new_col'] = df.apply(lambda x: '*'.join(x.dropna().astype(str).values), axis=1)
df
Out[76]:
  col1 col2 col3 new_col
0    a   ab    w  a*ab*w
1    b  NaN    e     b*e
2    3    4    6   3*4*6

另一个更新

In [81]:

df = pd.DataFrame({'col1' : ["a","b",3,'ñ'],
            'col2'  : ["ab",np.nan, 4,'ü'], 'col3' : ["w","e", 6,'á']})
df
Out[81]:
  col1 col2 col3
0    a   ab    w
1    b  NaN    e
2    3    4    6
3    ñ    ü    á

In [82]:

df['new_col'] = df.apply(lambda x: '*'.join(x.dropna().astype(str).values), axis=1)
​
df
Out[82]:
  col1 col2 col3 new_col
0    a   ab    w  a*ab*w
1    b  NaN    e     b*e
2    3    4    6   3*4*6
3    ñ    ü    á   ñ*ü*á

我的代码仍然能够处理西班牙语字符


看起来很完美。有一个问题,如果混合使用整数,Python 会出现问题。有没有办法在运行时将它们转换为字符串? - Bastien
谢谢!我也有烦人的字符(西班牙字母),所以我得到了以下错误:'ascii' codec can't encode character u'\xf3' in position 6: ordinal not in range(128) - Bastien
1
尝试解决最后一个错误,如果你无法解决,请提出另一个问题,因为它与你最初的问题无关。 - Julien Spronck

3
In [1556]: df.apply(lambda x: '*'.join(x.dropna().astype(str).values), axis=1)
Out[1556]: 
0    a*ab*w
1       b*e
2     3*4*�
3     ñ*ü*á
dtype: object

哎呀,没看到这个答案是第一个。太好了,我应该想到使用apply。我最终遇到了一些整数和特殊字符(比如西班牙字母)的问题。下面的答案解决了我的整数问题,但我还在等待如何处理像u'\xf3'这样的特殊字符的答案。 - Bastien
@Bastien 我的答案对于 ``'\xf3'` 仍然有效,但我正在运行 Python 3。 - EdChum

3

使用pandas.Series.str.cat函数:

import pandas as pd
import numpy as np

df = pd.DataFrame(dict(col1=["a","b"],
                       col2=["ab",np.nan], 
                       col3=["w","e"]))
df.T.apply(lambda c: c.str.cat(sep='*'))

将会给予

0    a*ab*w
1       b*e
dtype: object

如果你有整数、浮点数和字符串的混合,可以使用以下方法:

df.astype(str).T.apply(lambda c: c.replace('nan', np.nan).str.cat(sep='*'))

2
你可以使用 dropna() 函数。该函数用于从数据帧中删除缺失值。
df['col4'] = df.apply(lambda row: '*'.join(row.dropna()), axis=1)

更新:

由于您还需要转换数字和特殊字符,因此您可以使用 astype(unicode)

In [37]: df = pd.DataFrame({'col1': ["a", "b"], 'col2': ["ab", np.nan], "col3": [3, u'\xf3']})

In [38]: df.apply(lambda row: '*'.join(row.dropna().astype(unicode)), axis=1)
Out[38]: 
0    a*ab*3
1       b*ó
dtype: object

In [39]: df['col4'] = df.apply(lambda row: '*'.join(row.dropna().astype(unicode)), axis=1)

In [40]: df
Out[40]: 
  col1 col2 col3    col4
0    a   ab    3  a*ab*3
1    b  NaN    ó     b*ó

1
df.apply(lambda row: '*'.join(row.dropna()), axis=1)

1
for row in xrange(len(df)):
    s = '*'.join(df.ix[row].dropna().tolist())
    print s

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接