pandas.DataFrame, Seriesの要素の値を置換するreplace

Modified: | Tags: Python, pandas

pandasでDataFrame, Seriesの要素の値を置換するにはreplace()メソッドを使う。複数の異なる要素を一括で置換したり、正規表現で文字列の一部分のみを置換したりすることもできる。

Seriesに対してはmap()メソッドで置換することも可能。正規表現は使えないが、条件によってはreplace()よりmap()のほうが高速になる場合もある。

値を指定して置換するのではなく、条件に応じて値を置換する方法は以下の記事を参照。

本記事のサンプルコードのpandasのバージョンは以下の通り。バージョンによって仕様が異なる可能性があるので注意。例として以下のデータを使用する。説明のため一部要素の値を変更している。

import pandas as pd

print(pd.__version__)
# 2.1.2

df = pd.read_csv('data/src/sample_pandas_normal.csv')
df.iloc[1, 3] = 24
print(df)
#       name  age state  point
# 0    Alice   24    NY     64
# 1      Bob   42    CA     24
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57

例はDataFrameだがSeriesでも使い方は同じ。

要素を置換

第一引数に元の値、第二引数に置換後の値を指定する。

print(df.replace('CA', 'California'))
#       name  age       state  point
# 0    Alice   24          NY     64
# 1      Bob   42  California     24
# 2  Charlie   18  California     70
# 3     Dave   68          TX     70
# 4    Ellen   24  California     88
# 5    Frank   30          NY     57

すべての列の要素が対象となる。特定の列の値のみ置換したい場合については後述。

print(df.replace(24, 100))
#       name  age state  point
# 0    Alice  100    NY     64
# 1      Bob   42    CA    100
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen  100    CA     88
# 5    Frank   30    NY     57

デフォルトでは要素を置換した新たなDataFrameが返されるが、引数inplace=Trueとすると元のDataFrameが変更される。最後に例を紹介する。

複数の異なる要素を一括で置換

複数の異なる要素を一括で置き換えるには辞書かリストを使う。

辞書で指定

第一引数に{元の値: 置換後の値}の辞書を指定する。

print(df.replace({'CA': 'California', 24: 100}))
#       name  age       state  point
# 0    Alice  100          NY     64
# 1      Bob   42  California    100
# 2  Charlie   18  California     70
# 3     Dave   68          TX     70
# 4    Ellen  100  California     88
# 5    Frank   30          NY     57

リストで指定

第一引数に元の値のリスト、第二引数に置換後の値のリストを指定する。リストのサイズ(要素数)が一致していないとエラー。

print(df.replace(['CA', 24], ['California', 100]))
#       name  age       state  point
# 0    Alice  100          NY     64
# 1      Bob   42  California    100
# 2  Charlie   18  California     70
# 3     Dave   68          TX     70
# 4    Ellen  100  California     88
# 5    Frank   30          NY     57

# print(df.replace(['CA', 24, 'NY'], ['California', 100]))
# ValueError: Replacement lists must match in length. Expecting 3 got 2

第二引数にスカラー値を指定するとすべての要素がその値に置換される。

print(df.replace(['CA', 24], 'XXX'))
#       name  age state point
# 0    Alice  XXX    NY    64
# 1      Bob   42   XXX   XXX
# 2  Charlie   18   XXX    70
# 3     Dave   68    TX    70
# 4    Ellen  XXX   XXX    88
# 5    Frank   30    NY    57

対象列を指定して置換

第一引数に{列名: {元の値: 置換後の値}}の辞書を指定すると、対象列の要素のみを置換できる。辞書の要素を増やせば複数列・複数値を一括で置換可能。

print(df.replace({'age': {24: 100}}))
#       name  age state  point
# 0    Alice  100    NY     64
# 1      Bob   42    CA     24
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen  100    CA     88
# 5    Frank   30    NY     57

print(df.replace({'age': {24: 100, 18: 0}, 'point': {24: 50}}))
#       name  age state  point
# 0    Alice  100    NY     64
# 1      Bob   42    CA     50
# 2  Charlie    0    CA     70
# 3     Dave   68    TX     70
# 4    Ellen  100    CA     88
# 5    Frank   30    NY     57

元の値と置換後の値をリストで指定することはできない。

# print(df.replace({'age': [[24, 18], [100, 0]], 'point': {24: 50}}))
# TypeError: If a nested mapping is passed, all values of the top level mapping must be mappings

すべて同じ値に置換したい場合は、第一引数に{列名: 元の値}の辞書、第二引数に置換後の値をスカラー値で指定する。第一引数の元の値はリストで指定可能。

print(df.replace({'age': 24, 'point': 70}, 100))
#       name  age state  point
# 0    Alice  100    NY     64
# 1      Bob   42    CA     24
# 2  Charlie   18    CA    100
# 3     Dave   68    TX    100
# 4    Ellen  100    CA     88
# 5    Frank   30    NY     57

print(df.replace({'age': [24, 18], 'point': 70}, 100))
#       name  age state  point
# 0    Alice  100    NY     64
# 1      Bob   42    CA     24
# 2  Charlie  100    CA    100
# 3     Dave   68    TX    100
# 4    Ellen  100    CA     88
# 5    Frank   30    NY     57

正規表現で置換

引数regex=Trueとすると、正規表現を使うことができる。

デフォルトでは要素の値が完全に一致した場合のみ置換されるので、文字列の一部だけ一致していても置換されない。

print(df.replace('li', 'XX'))
#       name  age state  point
# 0    Alice   24    NY     64
# 1      Bob   42    CA     24
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57

regex=Trueとした場合は正規表現モジュールreのre.sub()を使って置換される。

第一引数に正規表現パターン、第二引数に置換後の文字列を指定する。例えばeで終わる文字列を置換する例は以下の通り。.が任意の文字、*が0回以上の繰り返し、$が文字列の末尾を表す。

print(df.replace('.*e$', 'NEW_NAME', regex=True))
#        name  age state  point
# 0  NEW_NAME   24    NY     64
# 1       Bob   42    CA     24
# 2  NEW_NAME   18    CA     70
# 3  NEW_NAME   68    TX     70
# 4     Ellen   24    CA     88
# 5     Frank   30    NY     57

正規表現の特殊文字を使わない場合、単純に指定した部分文字列が置換される。

print(df.replace('li', 'XX', regex=True))
#       name  age state  point
# 0    AXXce   24    NY     64
# 1      Bob   42    CA     24
# 2  CharXXe   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57

()で囲んだ部分をグループとして、置換後の値の中で\1, \2のように使うこともできる。

print(df.replace('(.*)li(.*)', r'\2-\1', regex=True))
#      name  age state  point
# 0    ce-A   24    NY     64
# 1     Bob   42    CA     24
# 2  e-Char   18    CA     70
# 3    Dave   68    TX     70
# 4   Ellen   24    CA     88
# 5   Frank   30    NY     57

re.sub()についての詳細は以下の記事を参照。

特定の列の要素の文字列の一部を置換したい場合は文字列メソッドstr.replace()を使う方法もある。

df['name'] = df['name'].str.replace('li', 'XX')
print(df)
#       name  age state  point
# 0    AXXce   24    NY     64
# 1      Bob   42    CA     24
# 2  CharXXe   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57

詳細は以下の記事参照。

欠損値NaNの置換

欠損値NaNの置換には、fillna()というメソッドが用意されている。詳細は以下の記事参照。

元のオブジェクトを変更

デフォルトでは要素を置換した新たなDataFrameが返されるが、引数inplace=Trueとすると元のDataFrameが変更される。

df = pd.read_csv('data/src/sample_pandas_normal.csv')
print(df)
#       name  age state  point
# 0    Alice   24    NY     64
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57

df.replace('CA', 'California', inplace=True)
print(df)
#       name  age       state  point
# 0    Alice   24          NY     64
# 1      Bob   42  California     92
# 2  Charlie   18  California     70
# 3     Dave   68          TX     70
# 4    Ellen   24  California     88
# 5    Frank   30          NY     57

関連カテゴリー

関連記事