Pandasで前処理を行う際に、文字列の処理に戸惑うことがよくあります。今回は、よく使いそうな文字列処理の方法をまとめていきます。ちなみに前処理全般については過去にまとめましたので、よろしければご覧ください。
また、Rユーザーの方はこちらを
データの作成
まずは今回文字列処理を行うためのデータセットを作成します。よくありがちな、一つのセルに複数の単語が入っていたり、大文字小文字なども汚いデータを想定します。
import pandas as pd import numpy as np register = ['name TANAKA\nnumber 1', 'name TANAKA\nnumber 1','name SATO', 'name YAMADA\nnumber 3','name KATO\nnumber 4'] fruits = ['apple 5', 'orange 4', 'Grape 3', 'Orange 10', np.nan] df = pd.DataFrame({'register':register, 'fruits':fruits}) df.head() register fruits 0 name TANAKA\nnumber 1 apple 5 1 name TANAKA\nnumber 1 orange 4 2 name SATO Grape 3 3 name YAMADA\nnumber 3 Orange 10 4 name KATO\nnumber 4 NaN
文字数カウント、大文字小文字変換
Pnadasで文字列処理を行うためには、str
アクセサを使います。使い方はSeries.str.hogehoge
です。基本的にはPandasのSeries形に対して処理を行います。とりあえず、文字列の長さ計算や、特定文字の個数カウント、大文字小文字変換など基本的な操作をやってみましょう。
str.len()
: 文字数の数を数える。str.count()
: 指定の文字数をカウントstr.lower()
:小文字に変換str.upper()
:大文字に変換str.title()
:1文字目を大文字に変換str.swapcase()
:大文字小文字の入れ替え
#文字数カウント print(df['register'].str.len()) >0 21 1 21 2 10 3 21 4 19 Name: register, dtype: int64 #特定の文字をカウント print(df['register'].str.count('T')) >0 1 1 1 2 1 3 0 4 1 Name: register, dtype: int64 #小文字 print(df['fruits'].str.lower()) >0 apple 5 1 orange 4 2 grape 3 3 orange 8 4 NaN Name: fruits, dtype: object #大文字 print(df['fruits'].str.upper()) >0 APPLE 5 1 ORANGE 4 2 GRAPE 3 3 ORANGE 8 4 NaN Name: fruits, dtype: object #最初の文字を大文字 print(df['fruits'].str.title()) >0 Apple 5 1 Orange 4 2 Grape 3 3 Orange 8 4 NaN Name: fruits, dtype: object #大文字小文字入れ替え print(df['fruits'].str.swapcase()) >0 APPLE 5 1 ORANGE 4 2 gRAPE 3 3 oRANGE 8 4 NaN Name: fruits, dtype: object
文字列の結合・分解
次に指定の文字列を結合・分解して新たな列として追加してみます。この辺りはデータの前処理ではよく使います。文字列の分解では、expandを指定すると、結果をSeries型とDataFrame型で指定できます。
str.cat()
: 文字列を結合str.split()
: 文字列を分解
#register列とfruits列を結合 #sepは結合させる文字 #na_repを指定すると欠損値も扱える。 df['register'].str.cat(df['fruits'],sep=' is ',na_rep='欠損です。') >0 name TANAKA\nnumber 1 is apple 5 1 name TANAKA\nnumber 1 is orange 4 2 name SATO is Grape 3 3 name YAMADA\nnumber 3 is Orange 10 4 name KATO\nnumber 4 is 欠損です。 Name: register, dtype: object #register列を改行\nで分解 #expand=Trueは結果をデータフレーム型で返す。 tmp = df['register'].str.split('\n',expand=True) #さらに空白で分解してデータフレームとして結合 pd.concat([tmp[0].str.split(expand=True),tmp[1].str.split(expand=True)]) 0 1 0 name TANAKA 1 name TANAKA 2 name SATO 3 name YAMADA 4 name KATO 0 number 1 1 number 1 2 None None 3 number 3 4 number 4
文字列の抽出
次に指定の文字列を含むかどうかの判断させたり、抽出したりしてみます。str.contains
とstr.extract
では正規表現が使えます。
str.contains(), str.startstiwh(), str.endsstiwh()
: 指定の文字列を含むかどうかstr.extract()
: 指定の文字列を抽出
#TAもしくはYAを含む print(df["register"].str.contains(r'(TA|YA)', regex=True)) >0 True 1 True 2 False 3 True 4 False #naで始まる print(df["register"].str.startswith('na')) >Name: register, dtype: bool 0 True 1 True 2 True 3 True 4 True Name: register, dtype: bool #3でおわる print(df["register"].str.endswith('3')) >0 False 1 False 2 False 3 True 4 False Name: register, dtype: bool #抜き出し系 #数字の抜き出し df['fruits'].str.extract(r'(\d+)',expand=True) 0 0 5 1 4 2 3 3 10 4 NaN #文字列と数字を別々に抜き出し df['fruits'].str.extract(r'(\D+)(\d+)',expand=True) 0 1 0 apple 5 1 orange 4 2 Grape 3 3 Orange 10 4 NaN NaN #列名を指定して抜き出し #(?P<列名>hogehoge)とする。 df['fruits'].str.extract(r'(?P<fruits>\D+)(?P<number>\d+)',expand=True) fruits num 0 apple 5 1 orange 4 2 Grape 3 3 Orange 10 4 NaN NaN
文字の加工
最後に文字を置換したり、長さをそろえたりしてみます。
str.pad()
:文字の長さを揃える。str.replace
:文字の置換
>数字を抜き出し、3文字になるように左側を0で埋める。 df['fruits'].str.extract(r'(\d+)',expand=False).str.pad(width=3, side='left', fillchar='0') >0 005 1 004 2 003 3 010 4 NaN Name: fruits, dtype: object #orangeをBananaに置換 #orangeは正規表現で df['fruits'].str.replace(r'(.range)', 'Banana') >0 apple 5 1 Banana 4 2 Grape 3 3 Banana 8 4 NaN Name: fruits, dtype: object
まとめ
Pythonではstrアクセサを使うと簡単に文字列処理を行うことができます。特に、自然言語処理などでは役立ちそうですね。
※本記事は筆者が個人的に学んだこと感じたことをまとめた記事になります。所属する組織の意見・見解とは無関係です。