pandasの文字列から正規表現で抽出して新たな列を生成

文字列を要素とするpandas.DataFrameの列、pandas.Seriesから正規表現で特定の文字列を抽出して新たな列を生成する方法を説明します。 以下の文字列メソッドを使います。

str.extract(): 最初のマッチ部分のみ抽出 str.extractall(): すべてのマッチ部分を抽出

以下のpandas.Seriesを例とします。

import pandas as pd

s_org = pd.Series(['aaa@xxx.com', 'bbb@yyy.net', 'ccc@zzz.co.jp'], index=['A', 'B', 'C'])
print(s_org)
# A      aaa@xxx.com
# B      bbb@yyy.net
# C    ccc@zzz.co.jp
# dtype: object

pandas.DataFrameの列から抽出したい場合はdf['列名']のように列(= pandas.Series)を指定してstr.extract()やstr.extractall()を呼べば問題ありません。

文字列の位置・長さを指定して抽出する場合はスライスを使うと簡単。以下の記事を参照。

str.extract(): 最初のマッチ部分のみ抽出

正規表現の最初のマッチ部分のみ抽出するにはstr.extract()メソッドを使います。

pandas.Series.str.extract — pandas 0.22.0 documentation

str.extract()の第一引数に正規表現パターンを指定すると() で囲まれたグループ部分にマッチする文字列が抽出される。 引数expandをTrueとするとpandas.DataFrame、Falseとするとpandas.Seriesとして新たなオブジェクトが生成される。

df_single = s_org.str.extract('(.+)@', expand=True)
print(df_single)
print(type(df_single))
#      0
# A  aaa
# B  bbb
# C  ccc
# <class 'pandas.core.frame.DataFrame'>

s = s_org.str.extract('(.+)@', expand=False)
print(s)
print(type(s))
# A    aaa
# B    bbb
# C    ccc
# dtype: object
# <class 'pandas.core.series.Series'>

現在のバージョン0.22.0ではexpand=Falseがデフォルトだが、将来的にはexpand=Trueがデフォルトになるとのこと。 FutureWarning: currently extract(expand=None) means expand=False (return Index/Series/DataFrame) but in a future version of pandas this will be changed to expand=True (return DataFrame)

正規表現パターンに名前付きグループ(?P...)を使うと名前がそのまま列名(カラム名)になる。

df_name = s_org.str.extract('(?P<local>.+)@', expand=True)
print(df_name)
print(type(df_name))
#   local
# A   aaa
# B   bbb
# C   ccc
# <class 'pandas.core.frame.DataFrame'>

()で囲まれたグループが複数あると、各グループで抽出された部分がそれぞれ列となるpandas.DataFrameが返る。引数expandがTrueでもFalseでもpandas.DataFrame。

df_multi = s_org.str.extract('(?P<local>.+)@(?P<domain>.+)', expand=True)
print(df_multi)
#   local     domain
# A   aaa    xxx.com
# B   bbb    yyy.net
# C   ccc  zzz.co.jp

なお、この例の場合はstr.split()メソッドで区切り文字を@として分割することも可能。文字列の分割については以下の記事を参照。

マッチする部分がない場合はNaNとなります。

df_nan = s_org.str.extract('(a+)', expand=True)
print(df_nan)
#      0
# A  aaa
# B  NaN
# C  NaN

str.extractall(): すべてのマッチ部分を抽出

正規表現のすべてのマッチ部分を抽出するにはstr.extractall()メソッドを使います。

pandas.Series.str.extractall — pandas 0.22.0 documentation

同じ正規表現パターンをstr.extract()とstr.extractall()に適用し、それぞれの結果を示す。

df_single = s_org.str.extract('(\w+)', expand=True)
print(df_single)
#      0
# A  aaa
# B  bbb
# C  ccc

df_all = s_org.str.extractall('(\w+)')
print(df_all)
#            0
#   match     
# A 0      aaa
#   1      xxx
#   2      com
# B 0      bbb
#   1      yyy
#   2      net
# C 0      ccc
#   1      zzz
#   2       co
#   3       jp

str.extractall()には引数expandは無く、常にindexがマルチインデックスのpandas.DataFrameを返す。

print(df_all.index)
# MultiIndex(levels=[['A', 'B', 'C'], [0, 1, 2, 3]],
#            labels=[[0, 0, 0, 1, 1, 1, 2, 2, 2, 2], [0, 1, 2, 0, 1, 2, 0, 1, 2, 3]],
#            names=[None, 'match'])

マルチインデックスのpandas.DataFrameの要素の指定・選択については以下の記事を参照。

シェア

関連カテゴリー

Python pandas

pandas.DataFrameをJSON文字列・ファイルに変換・保存(to_json) pandas参考書『Pythonによるデータ分析入門』の注意点 pandas.DataFrameの列をインデックス(行名)に割り当てるset_index pandas.DataFrameの行・列を指定して削除するdrop pandasで条件に応じて値を代入(where, mask) pandasのデータ型dtype一覧とastypeによる変換(キャスト) pandasのMultiIndexから任意の行・列を選択、抽出 pandasで日付・時間の列を処理(文字列変換、年月日抽出など) pandas.Seriesのmapメソッドで列の要素を置換 pandasのcrosstabでクロス集計(カテゴリ毎の出現回数・頻度を算出) pandasで特定の条件を満たす要素数をカウント(全体、行・列ごと) pandas.DataFrame, SeriesとPython標準のリストを相互に変換 pandasで欠損値NaNを前後の値から補間するinterpolate Python, pandas, seabornでペアプロット図(散布図行列)を作成

Last Updated: 6/26/2019, 10:34:03 PM