pandas.DataFrameの複数の列の文字列を結合して新たな列を生成

Modified: | Tags: Python, pandas

pandas.DataFrameの複数の列の文字列を結合(連結)して新たな列を生成する方法について、以下の内容を説明する。

  • 文字列の列同士の結合(連結)
    • str.cat()
    • +演算子
    • 欠損値NaNの処理
  • 文字列の列と数値の列の結合(連結)
  • 連結した列をpandas.DataFrameに追加

例として、以下のデータを使用する。

import pandas as pd

df = pd.read_csv('data/src/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

サンプルのcsvファイルはコチラ。

文字列の列同士の結合(連結)

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やリストでもよい。

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?

+演算子

単純に+演算子を使ってもOK。こちらのほうが直感的かもしれない。

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()を使う。

print(df['name'] + '-' + df['col_NaN'].fillna('No Data'))
# 0        Alice-X
# 1    Bob-No Data
# 2      Charlie-Z
# dtype: object

文字列の列と数値の列の結合(連結)

文字列の列と数値の列を結合する場合は、数値の列を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/src/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

関連カテゴリー

関連記事