pandas.DataFrame、pandas.Seriesの要素を置換する
環境
今回動作の確認を行った際のバージョンは下記の通り
python:3.10.9
pandas:1.5.3
データセット:scikit-learnのirisを使用(scikit-learnは1.2.2)
データセットの準備
前回と同じirisデータセットを使用して動作を確認していきます。
from sklearn.datasets import load_irisif __name__ == '__main__':df = load_iris(as_frame=True).frameprint(df.head())# sepal length (cm) sepal width (cm) ... petal width (cm) target# 0 5.1 3.5 ... 0.2 0# 1 4.9 3.0 ... 0.2 0# 2 4.7 3.2 ... 0.2 0# 3 4.6 3.1 ... 0.2 0# 4 5.0 3.6 ... 0.2 0# [5 rows x 5 columns]
replaceを使用した要素の置換
pandas.DataFrame、pandas.Seriesにはreplace()メソッドが用意されており、これを用いることで要素の置換を行うことが可能です。
pandas.Series.replace
pandas.DataFrame.replace
irisデータセットではtargetに0、1、2が設定されておりこれらはそれぞれsetosa、versicolor、virginicaを表しています。
from sklearn.datasets import load_irisif __name__ == '__main__':print(load_iris(as_frame=True).target_names)# ['setosa' 'versicolor' 'virginica']
今回は0、1、2をsetosa、versicolor、virginicaに変換してみます。
replace()メソッドは
replace('元の値', '置換後の値')
で置換することが可能です。
from sklearn.datasets import load_irisif __name__ == '__main__':df = load_iris(as_frame=True).frame# 最後の5行表示print(df.tail())# sepal length (cm) sepal width (cm) ... petal width (cm) target# 145 6.7 3.0 ... 2.3 2# 146 6.3 2.5 ... 1.9 2# 147 6.5 3.0 ... 2.0 2# 148 6.2 3.4 ... 2.3 2# 149 5.9 3.0 ... 1.8 2## [5 rows x 5 columns]# 花の種類をリストで取得target_name = load_iris(as_frame=True).target_names# for文を使用して花の種類を順番に置換for i, t in enumerate(target_name):df = df.replace(i, t)# 最後の5行表示print(df.tail())# sepal length (cm) sepal width (cm) ... petal width (cm) target# 145 6.7 3.0 ... 2.3 virginica# 146 6.3 2.5 ... 1.9 virginica# 147 6.5 3.0 ... virginica virginica# 148 6.2 3.4 ... 2.3 virginica# 149 5.9 3.0 ... 1.8 virginica## [5 rows x 5 columns]# target列をSeriesとして抽出s = df['target']# for文を使用して花の種類を順番に置換for i, t in enumerate(target_name):s = s.replace(i, t)# 最初の5行表示print(s.head())# 0 setosa# 1 setosa# 2 setosa# 3 setosa# 4 setosa# Name: target, dtype: object# 最後の5行表示print(s.tail())# 145 virginica# 146 virginica# 147 virginica# 148 virginica# 149 virginica# Name: target, dtype: object
引数に{'元の値':'置換後の値'}の様な辞書型データを渡すことでも同様に置換が可能です。
from sklearn.datasets import load_irisif __name__ == '__main__':df = load_iris(as_frame=True).frame# 最後の5行表示print(df.tail())# sepal length (cm) sepal width (cm) ... petal width (cm) target# 145 6.7 3.0 ... 2.3 2# 146 6.3 2.5 ... 1.9 2# 147 6.5 3.0 ... 2.0 2# 148 6.2 3.4 ... 2.3 2# 149 5.9 3.0 ... 1.8 2## [5 rows x 5 columns]# 花の種類をリストで取得target_name = load_iris(as_frame=True).target_namesprint(df.replace({0:target_name[0], 1:target_name[1], 2:target_name[2]}).tail())# sepal length (cm) sepal width (cm) ... petal width (cm) target# 145 6.7 3.0 ... 2.3 virginica# 146 6.3 2.5 ... 1.9 virginica# 147 6.5 3.0 ... virginica virginica# 148 6.2 3.4 ... 2.3 virginica# 149 5.9 3.0 ... 1.8 virginica## [5 rows x 5 columns]
しかしいずれの場合も上記の様に全列が置換対象となってしまいます。
{対象の列名:{'元の値':'置換後の値'}}という辞書型データを渡すことで特定の列のみを対象としてい置換することが可能です。
from sklearn.datasets import load_irisif __name__ == '__main__':df = load_iris(as_frame=True).frame# 最後の5行表示print(df.tail())# sepal length (cm) sepal width (cm) ... petal width (cm) target# 145 6.7 3.0 ... 2.3 2# 146 6.3 2.5 ... 1.9 2# 147 6.5 3.0 ... 2.0 2# 148 6.2 3.4 ... 2.3 2# 149 5.9 3.0 ... 1.8 2## [5 rows x 5 columns]# 花の種類をリストで取得target_name = load_iris(as_frame=True).target_namesprint(df.replace({'target':{0:target_name[0], 1:target_name[1], 2:target_name[2]}}).tail())# sepal length (cm) sepal width (cm) ... petal width (cm) target# 145 6.7 3.0 ... 2.3 virginica# 146 6.3 2.5 ... 1.9 virginica# 147 6.5 3.0 ... 2.0 virginica# 148 6.2 3.4 ... 2.3 virginica# 149 5.9 3.0 ... 1.8 virginica## [5 rows x 5 columns]
また、pandas.Series.replace、pandas.DataFrame.replaceには引数inplaceが用意されており、Trueを設定することで元のDataFrameをそのまま置換することが可能です。
from sklearn.datasets import load_irisif __name__ == '__main__':df = load_iris(as_frame=True).frame# 最後の5行表示print(df.tail())# sepal length (cm) sepal width (cm) ... petal width (cm) target# 145 6.7 3.0 ... 2.3 2# 146 6.3 2.5 ... 1.9 2# 147 6.5 3.0 ... 2.0 2# 148 6.2 3.4 ... 2.3 2# 149 5.9 3.0 ... 1.8 2## [5 rows x 5 columns]# 花の種類をリストで取得target_name = load_iris(as_frame=True).target_names# inplaceがFalse(デフォルト値)の場合df.replace({'target': {0: target_name[0], 1: target_name[1], 2: target_name[2]}})print(df)# sepal length (cm) sepal width (cm) ... petal width (cm) target# 0 5.1 3.5 ... 0.2 0# 1 4.9 3.0 ... 0.2 0# 2 4.7 3.2 ... 0.2 0# 3 4.6 3.1 ... 0.2 0# 4 5.0 3.6 ... 0.2 0# .. ... ... ... ... ...# 145 6.7 3.0 ... 2.3 2# 146 6.3 2.5 ... 1.9 2# 147 6.5 3.0 ... 2.0 2# 148 6.2 3.4 ... 2.3 2# 149 5.9 3.0 ... 1.8 2# [150 rows x 5 columns]# inplaceがTrueの場合df.replace({'target': {0: target_name[0], 1: target_name[1], 2: target_name[2]}}, inplace=True)print(df)# sepal length (cm) sepal width (cm) ... petal width (cm) target# 0 5.1 3.5 ... 0.2 0# 1 4.9 3.0 ... 0.2 0# 2 4.7 3.2 ... 0.2 0# 3 4.6 3.1 ... 0.2 0# 4 5.0 3.6 ... 0.2 0# .. ... ... ... ... ...# 145 6.7 3.0 ... 2.3 2# 146 6.3 2.5 ... 1.9 2# 147 6.5 3.0 ... 2.0 2# 148 6.2 3.4 ... 2.3 2# 149 5.9 3.0 ... 1.8 2# [150 rows x 5 columns]
正規表現を使って置換
pandas.Series.replace
pandas.DataFrame.replaceには引数regexが用意されており、Trueを設定することで正規表現を使用した置換が可能となります。
replaceは完全一致した値しか置換されないため正規表現を使用しない場合、例えば下記の様に置換が行われません。
from sklearn.datasets import load_irisif __name__ == '__main__':df = load_iris(as_frame=True).frame# 花の種類をリストで取得target_name = load_iris(as_frame=True).target_namesdf.replace({'target': {0: target_name[0], 1: target_name[1], 2: target_name[2]}}, inplace=True)print(df)# sepal length (cm) sepal width (cm) ... petal width (cm) target# 0 5.1 3.5 ... 0.2 setosa# 1 4.9 3.0 ... 0.2 setosa# 2 4.7 3.2 ... 0.2 setosa# 3 4.6 3.1 ... 0.2 setosa# 4 5.0 3.6 ... 0.2 setosa# .. ... ... ... ... ...# 145 6.7 3.0 ... 2.3 virginica# 146 6.3 2.5 ... 1.9 virginica# 147 6.5 3.0 ... 2.0 virginica# 148 6.2 3.4 ... 2.3 virginica# 149 5.9 3.0 ... 1.8 virginica# [150 rows x 5 columns]print(df.replace({'target':{'set':'SET'}}))# sepal length (cm) sepal width (cm) ... petal width (cm) target# 0 5.1 3.5 ... 0.2 setosa# 1 4.9 3.0 ... 0.2 setosa# 2 4.7 3.2 ... 0.2 setosa# 3 4.6 3.1 ... 0.2 setosa# 4 5.0 3.6 ... 0.2 setosa# .. ... ... ... ... ...# 145 6.7 3.0 ... 2.3 virginica# 146 6.3 2.5 ... 1.9 virginica# 147 6.5 3.0 ... 2.0 virginica# 148 6.2 3.4 ... 2.3 virginica# 149 5.9 3.0 ... 1.8 virginica# [150 rows x 5 columns]
正規表現を使うと部分的な置換も可能です。試しに「t(任意の文字列)s」を「TTT」に変換するという処理を実行してみると下記の様になります。
from sklearn.datasets import load_irisif __name__ == '__main__':df = load_iris(as_frame=True).frame# 花の種類をリストで取得target_name = load_iris(as_frame=True).target_namesdf.replace({'target': {0: target_name[0], 1: target_name[1], 2: target_name[2]}}, inplace=True)print(df)# sepal length (cm) sepal width (cm) ... petal width (cm) target# 0 5.1 3.5 ... 0.2 setosa# 1 4.9 3.0 ... 0.2 setosa# 2 4.7 3.2 ... 0.2 setosa# 3 4.6 3.1 ... 0.2 setosa# 4 5.0 3.6 ... 0.2 setosa# .. ... ... ... ... ...# 145 6.7 3.0 ... 2.3 virginica# 146 6.3 2.5 ... 1.9 virginica# 147 6.5 3.0 ... 2.0 virginica# 148 6.2 3.4 ... 2.3 virginica# 149 5.9 3.0 ... 1.8 virginica# [150 rows x 5 columns]print(df.replace('t.s', 'TTT', regex = True).head())# sepal length (cm) sepal width (cm) ... petal width (cm) target# 0 5.1 3.5 ... 0.2 seTTTa# 1 4.9 3.0 ... 0.2 seTTTa# 2 4.7 3.2 ... 0.2 seTTTa# 3 4.6 3.1 ... 0.2 seTTTa# 4 5.0 3.6 ... 0.2 seTTTa# .. ... ... ... ... ...# 145 6.7 3.0 ... 2.3 virginica# 146 6.3 2.5 ... 1.9 virginica# 147 6.5 3.0 ... 2.0 virginica# 148 6.2 3.4 ... 2.3 virginica# 149 5.9 3.0 ... 1.8 virginica# [150 rows x 5 columns]
Nanの置換
実データにおいて欠損値が含まれているケースは多々あります。そのような場合はreplace()を使わずpandas.DataFrame.fillnaを使用することで簡単に欠損値を変換することが出来ます。
irisデータセットにはNanが含まれていないため、意図的にデータを変換の上fillnaを実行してみます。
特定の値をnp.nanへ置換すればOKです。
from sklearn.datasets import load_irisif __name__ == '__main__':df = load_iris(as_frame=True).frame# 3.0をNanへ置換df.replace(3.0, np.nan, inplace=True)# 0.2をNanへ置換df.replace(0.2, np.nan, inplace=True)print(df)# sepal length (cm) sepal width (cm) ... petal width (cm) target# 0 5.1 3.5 ... NaN 0# 1 4.9 NaN ... NaN 0# 2 4.7 3.2 ... NaN 0# 3 4.6 3.1 ... NaN 0# 4 5.0 3.6 ... NaN 0# .. ... ... ... ... ...# 145 6.7 NaN ... 2.3 2# 146 6.3 2.5 ... 1.9 2# 147 6.5 NaN ... 2.0 2# 148 6.2 3.4 ... 2.3 2# 149 5.9 NaN ... 1.8 2# [150 rows x 5 columns]# Nanを1.0へ置換(穴埋め)df.fillna(1.0, inplace=True)print(df)# sepal length (cm) sepal width (cm) ... petal width (cm) target# 0 5.1 3.5 ... 1.0 0# 1 4.9 1.0 ... 1.0 0# 2 4.7 3.2 ... 1.0 0# 3 4.6 3.1 ... 1.0 0# 4 5.0 3.6 ... 1.0 0# .. ... ... ... ... ...# 145 6.7 1.0 ... 2.3 2# 146 6.3 2.5 ... 1.9 2# 147 6.5 1.0 ... 2.0 2# 148 6.2 3.4 ... 2.3 2# 149 5.9 1.0 ... 1.8 2# [150 rows x 5 columns]