11_Pandas.DataFrame中组合多个列的字符串来创建新列

以下对pandas.DataFrame的多列字符串通过合并(串联)来创建新列的方法进行说明。

  • 连接字符串
  • str.cat()
  • +运算符
  • NaN缺失值的处理
  • 字符串列和数值列的连接
  • 将串联的列添加到pandas.DataFrame

以下面的数据为例。

import pandas as pd

df = pd.read_csv('./data/11/sample_pandas_normal.csv').head(3)
print(df)
#       name  age state  point
# 0    Alice   24    NY     64
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70

连接字符串

str.cat()

可以使用字符串方法str.cat()连接字符串。

调用原pandas.Series和第一个参数中指定的pandas.Series的元素进行串联,返回一个pandas.Series。

print(df['name'].str.cat(df['state']))
# 0      AliceNY
# 1        BobCA
# 2    CharlieCA
# Name: name, dtype: object

如果为参数sep指定了字符串,则会在它们之间插入一个字符串。

print(df['name'].str.cat(df['state'], sep=' in '))
# 0      Alice in NY
# 1        Bob in CA
# 2    Charlie in CA
# Name: name, dtype: object

可以将具有相同数量元素的NumPy数组ndarray或list指定为第一个参数。

print(df['name'].str.cat(['X', 'Y', 'Z'], sep=' in '))
# 0      Alice in X
# 1        Bob in Y
# 2    Charlie in Z
# Name: name, dtype: object

也可以通过指定一个元素为pandas.Series的列表或一个列表作为第一个参数来连接多个字符串。

print(df['name'].str.cat([df['state'], ['X', 'Y', 'Z']], sep='-'))
# 0      Alice-NY-X
# 1        Bob-CA-Y
# 2    Charlie-CA-Z
# Name: name, dtype: object

可以将第一个参数指定为pandas.Series或它们的一个或多个列表,仅指定字符串是错误的。

# print(df['name'].str.cat('X', sep='-'))
# ValueError: Did you mean to supply a `sep` keyword?

+运算符

您可以简单地使用+运算符。这可能更直观。

print(df['name'] + df['state'])
# 0      AliceNY
# 1        BobCA
# 2    CharlieCA
# dtype: object

可以将相同的字符串连接到所有元素。

print(df['name'] + ' in ' + df['state'])
# 0      Alice in NY
# 1        Bob in CA
# 2    Charlie in CA
# dtype: object

具有相同数量的元素和列表串联的NumPy数组ndarray也是可。

print(df['name'] + ' in ' + df['state'] + ' - ' + ['X', 'Y', 'Z'])
# 0      Alice in NY - X
# 1        Bob in CA - Y
# 2    Charlie in CA - Z
# dtype: object

NaN缺失值的处理

如果包含缺失值NaN。

df['col_NaN'] = ['X', pd.np.nan, 'Z']
print(df)
#       name  age state  point col_NaN
# 0    Alice   24    NY     64       X
# 1      Bob   42    CA     92     NaN
# 2  Charlie   18    CA     70       Z

在str.cat()中,包含缺失值NaN的元素默认情况下变为缺失值NaN。

print(df['name'].str.cat(df['col_NaN'], sep='-'))
# 0      Alice-X
# 1          NaN
# 2    Charlie-Z
# Name: name, dtype: object

可以替换为参数na_rep指定的字符串。

print(df['name'].str.cat(df['col_NaN'], sep='-', na_rep='No Data'))
# 0        Alice-X
# 1    Bob-No Data
# 2      Charlie-Z
# Name: name, dtype: object

即使使用+运算符,包含缺失值NaN的元素也将变为缺失值NaN。

print(df['name'] + '-' + df['col_NaN'])
# 0      Alice-X
# 1          NaN
# 2    Charlie-Z
# dtype: object

如果要将缺失值NaN替换为任意值,请使用fillna()。

字符串列和数值列的连接

当组合字符串列和数字列时,必须通过astype()方法将数字列转换为字符串类型str。

# print(df['name'].str.cat(df['age'], sep='-'))
# TypeError: sequence item 1: expected str instance, int found

print(df['name'].str.cat(df['age'].astype(str), sep='-'))
# 0      Alice-24
# 1        Bob-42
# 2    Charlie-18
# Name: name, dtype: object

同样适用于+运算符。

# print(df['name'] + '-' + df['age'])
# TypeError: can only concatenate str (not "int") to str

print(df['name'] + '-' + df['age'].astype(str))
# 0      Alice-24
# 1        Bob-42
# 2    Charlie-18
# dtype: object

将串联的列添加到pandas.DataFrame

如果要将字符串连接的字符串作为新列添加到pandas.DataFrame中,请在[列名]中指定一个新列名并替换它。

df['name_state'] = df['name'].str.cat(df['state'], sep=' in ')
print(df)
#       name  age state  point col_NaN     name_state
# 0    Alice   24    NY     64       X    Alice in NY
# 1      Bob   42    CA     92     NaN      Bob in CA
# 2  Charlie   18    CA     70       Z  Charlie in CA

可以使用drop()方法删除不再需要的列。

print(df.drop(columns=['name', 'state']))
#    age  point col_NaN     name_state
# 0   24     64       X    Alice in NY
# 1   42     92     NaN      Bob in CA
# 2   18     70       Z  Charlie in CA

还有一种使用assign()的方法。使用assign()时,原始对象不会更改,并且会返回一个新对象。

df = pd.read_csv('./data/11/sample_pandas_normal.csv').head(3)
print(df)
#       name  age state  point
# 0    Alice   24    NY     64
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70

print(df.assign(name_state=df['name'] + ' in ' + df['state']))
#       name  age state  point     name_state
# 0    Alice   24    NY     64    Alice in NY
# 1      Bob   42    CA     92      Bob in CA
# 2  Charlie   18    CA     70  Charlie in CA

print(df.assign(name_state=df['name'] + ' in ' + df['state']).drop(columns=['name', 'state']))
#    age  point     name_state
# 0   24     64    Alice in NY
# 1   42     92      Bob in CA
# 2   18     70  Charlie in CA