本記事は、Pandas の公式ドキュメントのUser Guide - Working with text dataを機械翻訳した後、一部の不自然な文章を手直ししたものである。
誤訳の指摘・代訳案・質問等があればコメント欄や編集リクエストでお願いします。
テキストデータの操作
テキストデータの型
バージョン1.0.0で追加
pandasではテキストデータを保持する方法が2つあります。
-
object
データ型の NumPy 配列。 -
StringDtype
拡張型。
StringDtype
を使用してテキストデータを保持することをお勧めします。
pandas 1.0 以前は、object
データ型が唯一の方法でした。これは多くの理由で不便でした。
- 誤って文字列と非文字列を混在させて
object
データ型配列に格納する可能性があります。専用のデータ型があるのが良いでしょう。 -
object
データ型は、DataFrame.select_dtypes()
のようなデータ型固有の操作に適用できません。依然としてobjectデータ型の列である非テキスト列を除外しながら、テキストのみの列を選択する有効的な方法はありません。 - コードを読むとき、
obejct
データ型配列の内容は'string'
よりも明示的ではありません。
現在、文字列を格納したobject
データ型配列とarray.StringArray
のパフォーマンスはほぼ変わり有りません。今後の機能強化により、StringArray
のパフォーマンスが大幅に向上し、メモリオーバーヘッドが低下することが予想されます。
StringArray
は現在、実験的と見なされています。実装と部分的なAPIは、警告なしに変更される場合があります。
後方互換性のために、文字列のリストから推測する際のデフォルトの型は依然としてobject
データ型です。
pd.Series(["a", "b", "c"])
# 0 a
# 1 b
# 2 c
# dtype: object
string
データ型を明示的に要求するには、dtype
を指定します。
pd.Series(["a", "b", "c"], dtype="string")
# 0 a
# 1 b
# 2 c
# dtype: string
pd.Series(["a", "b", "c"], dtype=pd.StringDtype())
# 0 a
# 1 b
# 2 c
# dtype: string
または、既に存在するSeries
またはDataFrame
にastype
を適用して、
s = pd.Series(["a", "b", "c"])
s
# 0 a
# 1 b
# 2 c
# dtype: object
s.astype("string")
# 0 a
# 1 b
# 2 c
# dtype: string
バージョン 1.1.0 で変更
非文字列データを文字列データ型に変換するのにStringDtype
・"string"
を使用することもできます。
s = pd.Series(["a", 2, np.nan], dtype="string")
s
# 0 a
# 1 2
# 2 <NA>
# dtype: string
type(s[1])
# str
または、既に存在するpandasのデータを変換して、
s1 = pd.Series([1, 2, np.nan], dtype="Int64")
s1
# 0 1
# 1 2
# 2 <NA>
# dtype: Int64
s2 = s1.astype("string")
s2
# 0 1
# 1 2
# 2 <NA>
# dtype: string
type(s2[0])
# str
動作の違い
以下に、StringDtype
オブジェクトの動作がobject
データ型と異なる点を紹介します。
-
StringDtype
の場合、数値の出力を返す文字列アクセサメソッドは、欠損値の存在に応じて、整数または浮動小数データ型ではなく、常に欠損値許容整数データ型(Int64
データ型)を返します。真偽値の出力を返すメソッドは、欠損値許容真偽値データ型(boolean
データ型)を返します。s = pd.Series(["a", None, "b"], dtype="string") s # 0 a # 1 <NA> # 2 b # dtype: string s.str.count("a") # 0 1 # 1 <NA> # 2 0 # dtype: Int64 s.dropna().str.count("a") # 0 1 # 2 0 # dtype: Int64
両方とも出力は
Int64
データ型です。オブジェクトデータ型と比較してください。s2 = pd.Series(["a", None, "b"], dtype="object") s2.str.count("a") # 0 1.0 # 1 NaN # 2 0.0 # dtype: float64 s2.dropna().str.count("a") # 0 1 # 2 0 # dtype: int64
オブジェクトデータ型では、欠損値が存在する場合、出力データ型はfloat64になります。真偽値を返すメソッドの場合も同様です。
s.str.isdigit() # 0 False # 1 <NA> # 2 False # dtype: boolean s.str.match("a") # 0 True # 1 <NA> # 2 False # dtype: boolean
-
StringArray
はバイトではなく文字列のみを保持するため、Series.str.decode()
などの一部の文字列メソッドはStringArray
では使用できません。 -
比較操作では、
array.StringArray
およびStringArray
を基にしたSeries
は、bool
データ型オブジェクトではなくBooleanDtype
のオブジェクトを返します。StringArray
の欠損値は、numpy.nan
のように常に等しくないという結果を返すのではなく、比較演算を行っても伝播します。
このドキュメントの以下で紹介する、その他の関数・メソッド等は、string
とobject
データ型に等しく適用されます。
文字列メソッド
Series および Index には、配列の各要素を簡単に操作できる一連の文字列処理メソッドが実装されています。これらのメソッドが欠損値・ NA 値を自動的に除外することは、重要なことかもしれません。これらはstr
属性を介してアクセスされ、多くの場合、同等の(スカラー)組み込み文字列メソッドに一致する名前を持ちます。
s = pd.Series(
["A", "B", "C", "Aaba", "Baca", np.nan, "CABA", "dog", "cat"], dtype="string"
)
s.str.lower()
# 0 a
# 1 b
# 2 c
# 3 aaba
# 4 baca
# 5 <NA>
# 6 caba
# 7 dog
# 8 cat
# dtype: string
s.str.upper()
# 0 A
# 1 B
# 2 C
# 3 AABA
# 4 BACA
# 5 <NA>
# 6 CABA
# 7 DOG
# 8 CAT
# dtype: string
s.str.len()
# 0 1
# 1 1
# 2 1
# 3 4
# 4 4
# 5 <NA>
# 6 4
# 7 3
# 8 3
# dtype: Int64
idx = pd.Index([" jack", "jill ", " jesse ", "frank"])
idx.str.strip()
# Index(['jack', 'jill', 'jesse', 'frank'], dtype='object')
idx.str.lstrip()
# Index(['jack', 'jill ', 'jesse ', 'frank'], dtype='object')
idx.str.rstrip()
# Index([' jack', 'jill', ' jesse', 'frank'], dtype='object')
Indexにおける文字列メソッドは、データフレームの列のクリーンアップまたは変換に特に役立ちます。たとえば、先頭または末尾に空白がある列がある場合を考えます。
df = pd.DataFrame(
np.random.randn(3, 2), columns=[" Column A ", " Column B "], index=range(3)
)
df
# Column A Column B
# 0 0.469112 -0.282863
# 1 -1.509059 -1.135632
# 2 1.212112 -0.173215
df.columns
はインデックスオブジェクトなので、.str
アクセサを使用できます。
df.columns.str.strip()
# Index(['Column A', 'Column B'], dtype='object')
df.columns.str.lower()
# Index([' column a ', ' column b '], dtype='object')
これらの文字列メソッドを使用して、必要に応じて列をクリーンアップできます。次の例は、先頭と末尾の空白を削除し、すべての名前を小文字にし、残りの空白をアンダースコアに置き換えています。
df.columns = df.columns.str.strip().str.lower().str.replace(" ", "_")
df
# column_a column_b
# 0 0.469112 -0.282863
# 1 -1.509059 -1.135632
# 2 1.212112 -0.173215
多数の要素が繰り返されるSeries
がある場合(つまり、Series
内の一意の要素の数がSeries
の長さよりもはるかに小さい場合)、元のSeries
をcategory
型に変換したものを作成し、それに対して.str.<method>
や.dt.<property>
を適用する方が高速です。このパフォーマンスの違いは、category
型のSeries
の場合、文字列操作はSeries
の各要素ではなく.categories
で実行されることによります。
文字列の.categories
を持つcategory
型のSeries
には、文字列型のSeries
と比較していくつかの制限があることに注意してください(例えばs + " " + s
は、s
がcategory
型のSeries
の場合機能しません。)。また、list
型の要素を操作する.str
メソッドも、そのようなSeries
では使用できません。
バージョン0.25.0以前は、.str
アクセサは最も初歩的な型チェックのみを行いました。バージョン0.25.0以降、より厳密に、シリーズの型が推測され、許容される型(つまり文字列)が適用されます。
一般的に、.str
アクセサは文字列でのみ機能するように設計されています。非常に少数の例外を除いて、他の用途はサポートされておらず、後で無効になる可能性があります。
文字列の分割と置換
split
などのメソッドは、リストからなるSeries
を返します。
s2 = pd.Series(["a_b_c", "c_d_e", np.nan, "f_g_h"], dtype="string")
s2.str.split("_")
# 0 [a, b, c]
# 1 [c, d, e]
# 2 <NA>
# 3 [f, g, h]
# dtype: object
分割したリストの要素には、get
または[]
表記を使用してアクセスできます。
s2.str.split("_").str.get(1)
# 0 b
# 1 d
# 2 <NA>
# 3 g
# dtype: object
s2.str.split("_").str[1]
# 0 b
# 1 d
# 2 <NA>
# 3 g
# dtype: object
expand
引数によって簡単に、これを展開してDataFrame
として返すことができます。
s2.str.split("_", expand=True)
# 0 1 2
# 0 a b c
# 1 c d e
# 2 <NA> <NA> <NA>
# 3 f g h
元のSeries
にStringDtype
がある場合、出力列もすべてStringDtype
になります。
分割数を制限することもできます。
s2.str.split("_", expand=True, n=1)
# 0 1
# 0 a b_c
# 1 c d_e
# 2 <NA> <NA>
# 3 f g_h
rsplit
はsplit
と似ていますが、逆方向、つまり文字列の末尾から文字列の先頭に向かって動作する点が異なります。
s2.str.rsplit("_", expand=True, n=1)
# 0 1
# 0 a_b c
# 1 c_d e
# 2 <NA> <NA>
# 3 f_g h
replace
はオプションで正規表現を使用します。
(訳注:Series.str.replace()
のregex
オプションのデフォルトは現在True
になっているが、将来False
に変更される予定)
s3 = pd.Series(
["A", "B", "C", "Aaba", "Baca", "", np.nan, "CABA", "dog", "cat"],
dtype="string",
)
s3
# 0 A
# 1 B
# 2 C
# 3 Aaba
# 4 Baca
# 5
# 6 <NA>
# 7 CABA
# 8 dog
# 9 cat
# dtype: string
s3.str.replace("^.a|dog", "XX-XX ", case=False, regex=True)
# 0 A
# 1 B
# 2 C
# 3 XX-XX ba
# 4 XX-XX ca
# 5
# 6 <NA>
# 7 XX-XX BA
# 8 XX-XX
# 9 XX-XX t
# dtype: string
正規表現を扱う際には、いくつかの注意が必要です。現在の動作では、regex
がTrue
に設定されている場合でも、1文字のパターンをリテラル文字列として扱います。この動作は非推奨で、将来のバージョンでは削除され、regex
キーワードが常に尊重されるようになる予定です。
バージョン1.2.0で変更
(str.replace()
と同様の)文字列のリテラル置換を行いたい場合は、各文字をエスケープするのではなく、オプションのregex
パラメータをFalse
に設定します。この場合、pat
とrepl
は両方とも文字列でなければなりません。
dollars = pd.Series(["12", "-$10", "$10,000"], dtype="string")
# 次の2つは同等
dollars.str.replace(r"-\$", "-", regex=True)
# 0 12
# 1 -10
# 2 $10,000
# dtype: string
dollars.str.replace("-$", "-", regex=False)
# 0 12
# 1 -10
# 2 $10,000
# dtype: string
replace
メソッドは、関数を呼び出して置換することもできます。re.sub()
を使用して、すべてのpat
に対して呼び出されます。呼び出し可能オブジェクトは、1つの位置引数(正規表現オブジェクト)を受け取り、文字列を返す必要があります。
# 小文字のアルファベットの綴りをすべて反転させる
pat = r"[a-z]+"
def repl(m):
return m.group(0)[::-1]
pd.Series(["foo 123", "bar baz", np.nan], dtype="string").str.replace(
pat, repl, regex=True
)
# 0 oof 123
# 1 rab zab
# 2 <NA>
# dtype: string
# 正規表現グループを使用
pat = r"(?P<one>\w+) (?P<two>\w+) (?P<three>\w+)"
def repl(m):
return m.group("two").swapcase()
pd.Series(["Foo Bar Baz", np.nan], dtype="string").str.replace(
pat, repl, regex=True
)
# 0 bAR
# 1 <NA>
# dtype: string
replace
メソッドは、パターンとしてre.compile()
からコンパイルされた正規表現オブジェクトも受け入れます。すべてのフラグは、コンパイル済みの正規表現オブジェクトに含める必要があります。
import re
regex_pat = re.compile(r"^.a|dog", flags=re.IGNORECASE)
s3.str.replace(regex_pat, "XX-XX ", regex=True)
# 0 A
# 1 B
# 2 C
# 3 XX-XX ba
# 4 XX-XX ca
# 5
# 6 <NA>
# 7 XX-XX BA
# 8 XX-XX
# 9 XX-XX t
# dtype: string
コンパイルされた正規表現オブジェクトでreplace
を呼び出すときにflags
引数を使うと、ValueError
が発生します。
s3.str.replace(regex_pat, 'XX-XX ', flags=re.IGNORECASE)
# ---------------------------------------------------------------------------
# ValueError: case and flags cannot be set when pat is a compiled regex
removeprefix
とremovesuffix
は、Python 3.9で追加されたstr.removeprefix
とstr.removesuffix
と同じ効果を持っています。
バージョン1.4.0で追加
s = pd.Series(["str_foo", "str_bar", "no_prefix"])
s.str.removeprefix("str_")
# 0 foo
# 1 bar
# 2 no_prefix
# dtype: object
s = pd.Series(["foo_str", "bar_str", "no_suffix"])
s.str.removesuffix("_str")
# 0 foo
# 1 bar
# 2 no_suffix
# dtype: object
結合
series
やIndex
をそれ自体ないし他と結合するには、すべてcat()
またはIndex.str.cat
に基づいたいくつかの方法があります。
単一のSeriesと文字列の結合
Series
(またはIndex
)の各要素を結合できます。
s = pd.Series(["a", "b", "c", "d"], dtype="string")
s.str.cat(sep=",")
# 'a,b,c,d'
区切り文字を指定する引数sep
が指定されていない場合、デフォルトとして空の文字列sep=''
になります。
s.str.cat()
# 'abcd'
デフォルトでは、欠損値は無視されます。na_rep
を使用して、表現を指定できます。
t = pd.Series(["a", "b", np.nan, "d"], dtype="string")
t.str.cat(sep=",")
# 'a,b,d'
t.str.cat(sep=",", na_rep="-")
# 'a,b,-,d'
Seriesにリスト等を結合
cat()
の最初の引数には、呼び出し元のSeries
(またはIndex
)の長さと一致する、リストライクなオブジェクトを渡すことができます。
s.str.cat(["A", "B", "C", "D"])
# 0 aA
# 1 bB
# 2 cC
# 3 dD
# dtype: string
na_rep
が指定されていない場合、どちらか一方にでも欠損値があれば、結果も欠損値になります。
s.str.cat(t)
# 0 aa
# 1 bb
# 2 <NA>
# 3 dd
# dtype: string
s.str.cat(t, na_rep="-")
# 0 aa
# 1 bb
# 2 c-
# 3 dd
# dtype: string
Seriesに配列等を結合
others
パラメーターには2次元のデータを渡すこともできます。この場合、行数は呼び出し元のSeries
(またはIndex
)の長さと一致する必要があります。
d = pd.concat([t, s], axis=1)
s
# 0 a
# 1 b
# 2 c
# 3 d
# dtype: string
d
# 0 1
# 0 a a
# 1 b b
# 2 <NA> c
# 3 d d
s.str.cat(d, na_rep="-")
# 0 aaa
# 1 bbb
# 2 c-c
# 3 ddd
# dtype: string
Series にインデックスに基づいてオブジェクトを結合
Series
またはDataFrame
との結合の場合、join
キーワードを設定することにより、結合する前にインデックスを調整できます。
u = pd.Series(["b", "d", "a", "c"], index=[1, 3, 0, 2], dtype="string")
s
# 0 a
# 1 b
# 2 c
# 3 d
# dtype: string
u
# 1 b
# 3 d
# 0 a
# 2 c
# dtype: string
s.str.cat(u)
# 0 aa
# 1 bb
# 2 cc
# 3 dd
# dtype: string
s.str.cat(u, join="left")
# 0 aa
# 1 bb
# 2 cc
# 3 dd
# dtype: string
join
キーワードが渡されなかった場合、cat()
メソッドは現在、バージョン0.23.0より前の動作(つまり、整列なし)にフォールバックしますが、将来のバージョンではこのデフォルトがjoin='left'
に変更されるため、関連するインデックスのいずれかが異なる場合はFutureWarning
が発生します。
join
には通常のオプションを使用できます('left', 'outer', 'inner', 'right'
のいずれか)。ここで行われるアラインメントは、長さを一致させる必要がないことも意味します。
v = pd.Series(["z", "a", "b", "d", "e"], index=[-1, 0, 1, 3, 4], dtype="string")
s
# 0 a
# 1 b
# 2 c
# 3 d
# dtype: string
v
# -1 z
# 0 a
# 1 b
# 3 d
# 4 e
# dtype: string
s.str.cat(v, join="left", na_rep="-")
# 0 aa
# 1 bb
# 2 c-
# 3 dd
# dtype: string
s.str.cat(v, join="outer", na_rep="-")
# -1 -z
# 0 aa
# 1 bb
# 2 c-
# 3 dd
# 4 -e
# dtype: string
同様に、others
がDataFrame
であっても実行可能です。
f = d.loc[[3, 2, 1, 0], :]
s
# 0 a
# 1 b
# 2 c
# 3 d
# dtype: string
f
# 0 1
# 3 d d
# 2 <NA> c
# 1 b b
# 0 a a
s.str.cat(f, join="left", na_rep="-")
# 0 aaa
# 1 bbb
# 2 c-c
# 3 ddd
# dtype: string
Series と複数のオブジェクトの結合
複数の配列ライクのオブジェクト(具体的には、Series
・Index
・および1次元のnp.ndarray
バリアント)は、リストライクなコンテナ(イテレータやdict
-views などを含む)を用いて結合することができます。
s
# 0 a
# 1 b
# 2 c
# 3 d
# dtype: string
u
# 1 b
# 3 d
# 0 a
# 2 c
# dtype: string
s.str.cat([u, u.to_numpy()], join="left")
# 0 aab
# 1 bbd
# 2 cca
# 3 ddc
# dtype: string
渡されたリストのうち、インデックスのない要素(例:np.ndarray
)は呼び出し元のSeries
(またはIndex
)と長さが一致している必要がありますが、Series
やIndex
は(join=None
で整列が無効にされていない限り)長さは自由です。
v
# -1 z
# 0 a
# 1 b
# 3 d
# 4 e
# dtype: string
s.str.cat([v, u, u.to_numpy()], join="outer", na_rep="-")
# -1 -z--
# 0 aaab
# 1 bbbd
# 2 c-ca
# 3 dddc
# 4 -e--
# dtype: string
others
に渡したリストが異なるインデックスを含む状態でjoin='right'
を指定した場合、返されるオブジェクトはこれらのインデックスの和(union)に基づいて形成されます。
u.loc[[3]]
# 3 d
# dtype: string
v.loc[[-1, 0]]
# -1 z
# 0 a
# dtype: string
s.str.cat([u.loc[[3]], v.loc[[-1, 0]]], join="right", na_rep="-")
# 3 dd-
# -1 --z
# 0 a-a
# dtype: string
.str
を用いた索引
[]
記法を使用して、位置の場所を指定することで直接索引できます。文字列の末尾を超えて索引すると、結果はNaN
になります。
s = pd.Series(
["A", "B", "C", "Aaba", "Baca", np.nan, "CABA", "dog", "cat"], dtype="string"
)
s.str[0]
# 0 A
# 1 B
# 2 C
# 3 A
# 4 B
# 5 <NA>
# 6 C
# 7 d
# 8 c
# dtype: string
s.str[1]
# 0 <NA>
# 1 <NA>
# 2 <NA>
# 3 a
# 4 a
# 5 <NA>
# 6 A
# 7 o
# 8 a
# dtype: string
部分文字列の抽出
各要素の最初の一致を抽出(extract)
バージョン0.23以前は、extract
メソッドのexpand
引数のデフォルトはFalse
に設定されていました。expand=False
の場合、expand
は、対象文字列と正規表現パターンに応じて、Series
・Index
・DataFrame
のいずれかを返します。expand=True
の場合は、常にDataFrame
を返します。これはユーザーの観点から見ると、より一貫性があり混乱が少ないです。expand=True
は、バージョン0.23.0以降はデフォルトになりました。
extract
メソッドは、少なくとも1つのキャプチャグループを持つ正規表現を受け取ります。
複数のグループを持つ正規表現を抽出すると、グループごとに1つの列を持つデータフレームが返されます。
pd.Series(
["a1", "b2", "c3"],
dtype="string",
).str.extract(r"([ab])(\d)", expand=False)
# 0 1
# 0 a 1
# 1 b 2
# 2 <NA> <NA>
一致しない要素は、NaN
で満たされた行を返します。したがって、乱雑な文字列のシリーズは、タプルまたはre.match
オブジェクトにアクセスするのにget()
を必要とせずに、クリーンアップされた、またはより有用な文字列の同様のインデックス付きシリーズまたはデータフレームに「変換」できます。一致が見つからず、結果がNaN
のみであっても、データ型は常にオブジェクトです(訳注:元がstring
の場合はstring
になるはず)。
名前付きグループや、
pd.Series(["a1", "b2", "c3"], dtype="string").str.extract(
r"(?P<letter>[ab])(?P<digit>\d)", expand=False
)
# letter digit
# 0 a 1
# 1 b 2
# 2 <NA> <NA>
オプションのグループ
pd.Series(
["a1", "b2", "3"],
dtype="string",
).str.extract(r"([ab])?(\d)", expand=False)
# 0 1
# 0 a 1
# 1 b 2
# 2 <NA> 3
を使用することもできます。正規表現のキャプチャグループ名は、それぞれの列名に使用されることを覚えておいてください。キャプチャグループ名が存在しない場合は、キャプチャグループ番号が使用されます。
グループを1つだけ持つ正規表現によって抽出すると、expand=True
の場合、1つの列からなるDataFrame
が返されます。
pd.Series(["a1", "b2", "c3"], dtype="string").str.extract(r"[ab](\d)", expand=True)
# 0
# 0 1
# 1 2
# 2 <NA>
expand=False
の場合は、Seires
が返されます。
pd.Series(["a1", "b2", "c3"], dtype="string").str.extract(r"[ab](\d)", expand=False)
# 0 1
# 1 2
# 2 <NA>
# dtype: string
Index
に対してキャプチャグループをちょうど1つだけ持つ正規表現で呼び出すと、expand=True
の場合、1つの列からなるDataFrame
が返されます。
s = pd.Series(["a1", "b2", "c3"], ["A11", "B22", "C33"], dtype="string")
s
# A11 a1
# B22 b2
# C33 c3
# dtype: string
s.index.str.extract("(?P<letter>[a-zA-Z])", expand=True)
# letter
# 0 A
# 1 B
# 2 C
expand=False
の場合は、Index
が返されます。
s.index.str.extract("(?P<letter>[a-zA-Z])", expand=False)
# Index(['A', 'B', 'C'], dtype='object', name='letter')
Index
に対してキャプチャグループを複数持つ正規表現で呼び出すと、expand=True
の場合、DataFrame
が返されます。
s.index.str.extract("(?P<letter>[a-zA-Z])([0-9]+)", expand=True)
# letter 1
# 0 A 11
# 1 B 22
# 2 C 33
expand=False
の場合は、ValueError
が発生します。
s.index.str.extract("(?P<letter>[a-zA-Z])([0-9]+)", expand=False)
# ValueError: only one regex group is supported with Index
次の表は、extract(expand=False)
の動作をまとめたものです(1列目は入力サブジェクト、1行目は正規表現のグループ数)。
1 グループ | >1 グループ | |
---|---|---|
Index | Index | ValueError |
Series | Series | DataFrame |
各要素のすべての一致を抽出(extractall)
(最初の一致のみを抽出する)extract
とは異なり、
s = pd.Series(["a1a2", "b1", "c1"], index=["A", "B", "C"], dtype="string")
s
# A a1a2
# B b1
# C c1
# dtype: string
two_groups = "(?P<letter>[a-z])(?P<digit>[0-9])"
s.str.extract(two_groups, expand=True)
# letter digit
# A a 1
# B b 1
# C c 1
extractall
メソッドはすべての一致を返します。extractall
の結果は常に、MultiIndex
を行に持つDataFrame
です。MultiIndex
の最低レベルはmatch
という名前で、要素の順序を示します。
s.str.extractall(two_groups)
# letter digit
# match
# A 0 a 1
# 1 a 2
# B 0 b 1
# C 0 c 1
Series の各要素の文字列に1回だけ一致する場合、
s = pd.Series(["a3", "b3", "c2"], dtype="string")
s
# 0 a3
# 1 b3
# 2 c2
# dtype: string
extractall(pat).xs(0, level='match')
は、extract(pat)
と同じ結果になります。
extract_result = s.str.extract(two_groups, expand=True)
extract_result
# letter digit
# 0 a 3
# 1 b 3
# 2 c 2
extractall_result = s.str.extractall(two_groups)
extractall_result
# letter digit
# match
# 0 0 a 3
# 1 0 b 3
# 2 0 c 2
extractall_result.xs(0, level="match")
# letter digit
# 0 a 3
# 1 b 3
# 2 c 2
Index
も.str.extractall
をサポートしています。デフォルトの(0から始まる)インデックスを持つSeries.str.extractall
と同じ結果の、DataFrame
を返します。
pd.Index(["a1a2", "b1", "c1"]).str.extractall(two_groups)
# letter digit
# match
# 0 0 a 1
# 1 a 2
# 1 0 b 1
# 2 0 c 1
pd.Series(["a1a2", "b1", "c1"], dtype="string").str.extractall(two_groups)
# letter digit
# match
# 0 0 a 1
# 1 a 2
# 1 0 b 1
# 2 0 c 1
パターンに一致する、またはパターンを含む文字列のテスト
要素にパターンが含まれているかどうかを確認できます。
pattern = r"[0-9][a-z]"
pd.Series(
["1", "2", "3a", "3b", "03c", "4dx"],
dtype="string",
).str.contains(pattern)
# 0 False
# 1 False
# 2 True
# 3 True
# 4 True
# 5 True
# dtype: boolean
また、要素がパターンに一致するかどうかも確認できます。
pd.Series(
["1", "2", "3a", "3b", "03c", "4dx"],
dtype="string",
).str.match(pattern)
# 0 False
# 1 False
# 2 True
# 3 True
# 4 False
# 5 True
# dtype: boolean
バージョン1.1.0で追加
pd.Series(
["1", "2", "3a", "3b", "03c", "4dx"],
dtype="string",
).str.fullmatch(pattern)
# 0 False
# 1 False
# 2 True
# 3 True
# 4 False
# 5 False
# dtype: boolean
match
・fullmatch
・contains
の違いは厳密さです。fullmatch
は文字列全体が正規表現にマッチするかどうかをテストし、match
は文字列の先頭を見て正規表現にマッチするかどうかをテストし、contains
は文字列内の任意の位置に正規表現にマッチする部分があるかどうかをテストします。
これら3つの一致モードは、re
パッケージにおけるre.fullmatch・re.match・re.searchにそれぞれ対応します。
match
・fullmatch
・contains
・startswith
・endswith
などのメソッドはオプションのna
引数を受け取って、欠損値をTrueまたはFalseと見なすことができます。
s4 = pd.Series(
["A", "B", "C", "Aaba", "Baca", np.nan, "CABA", "dog", "cat"], dtype="string"
)
s4.str.contains("A", na=False)
# 0 True
# 1 False
# 2 False
# 3 True
# 4 False
# 5 False
# 6 True
# 7 False
# 8 False
# dtype: boolean
標識変数の作成
文字列の列をダミー変数化できます。たとえば、|
で区切られている場合、
s = pd.Series(["a", "a|b", np.nan, "a|c"], dtype="string")
s.str.get_dummies(sep="|")
# a b c
# 0 1 0 0
# 1 1 1 0
# 2 0 0 0
# 3 1 0 1
文字列Index
も、MultiIndex
を返すget_dummies
をサポートしています。
idx = pd.Index(["a", "a|b", np.nan, "a|c"])
idx.str.get_dummies(sep="|")
# MultiIndex([(1, 0, 0),
# (1, 1, 0),
# (0, 0, 0),
# (1, 0, 1)],
# names=['a', 'b', 'c'])
get_dummies()
についての説明もご覧ください。
主なメソッド
メソッド | 説明 |
---|---|
cat() |
文字列を連結 |
split() |
区切り文字を指定して文字列を分割 |
rsplit() |
区切り文字を指定して文字列を末尾から分割 |
get() |
各要素へのインデックス(i 番目の要素を取得) |
join() |
渡された区切り文字でシリーズの各要素の文字列を結合 |
get_dummies() |
区切り文字を指定して文字列を分割し、ダミー変数化した DataFrame を返す |
contains() |
各文字列にパターン・正規表現が含まれるかどうかの、真偽値配列を返す |
replace() |
パターン・正規表現・文字列に一致する部分を、他の文字列または呼び出し可能オブジェクトの戻り値に置換 |
removeprefix() |
文字列から接頭辞を取り除く、つまり、文字列が接頭辞で始まる場合のみ取り除く |
removesuffix() |
文字列から接尾辞を取り除く、つまり、文字列が接尾辞で終わる場合のみ取り除く |
repeat() |
文字列を複製(s.str.repeat(3) はx * 3 に等しい) |
pad() |
文字列の左・右または両側に空白を追加 |
center() |
str.center に同じ |
ljust() |
str.ljust に同じ |
rjust() |
str.rjust に同じ |
zfill() |
str.zfill に同じ |
wrap() |
長い文字列を指定した値以下の長さの行に分割 |
slice() |
Series の各文字列をスライス |
slice_replace() |
スライスした Series の各文字列を、指定した値に置換 |
count() |
パターンの出現回数をカウント |
startswith() |
各要素に対してstr.startswith(pat) を適用するのと同じ |
endswith() |
各要素に対してstr.endswith(pat) を適用するのと同じ |
findall() |
各文字列に対して、全てのパターン・正規表現の一致リストを返す |
match() |
各要素に対してre.match を適用し、パターン・正規表現に一致するかどうかの真偽値配列を返す |
extract() |
各要素に対してre.search を適用し、各要素が行、各正規表現キャプチャグループが列の DataFrame を返す |
extractall() |
各要素に対してre.findall を適用し、各要素が行、各正規表現キャプチャグループが列の DataFrame を返す |
len() |
文字列の長さ |
strip() |
str.strip に同じ |
rstrip() |
str.rstrip に同じ |
lstrip() |
str.lstrip に同じ |
partition() |
str.partition に同じ |
rpartition() |
str.rpartition に同じ |
lower() |
str.lower に同じ |
casefold() |
str.casefold に同じ |
upper() |
str.upper に同じ |
find() |
str.find に同じ |
rfind() |
str.rfind に同じ |
index() |
str.index に同じ |
rindex() |
str.rindex に同じ |
capitalize() |
str.capitalize に同じ |
swapcase() |
str.swapcase に同じ |
normalize() |
Unicode 標準形式を返す。unicodedata.nnormalize に同じ |
translate() |
str.translate に同じ |
isalnum() |
str.isalnum に同じ |
isalpha() |
str.isalpha に同じ |
isdigit() |
str.isdigit に同じ |
isspace() |
str.isspace に同じ |
islower() |
str.islower に同じ |
isupper() |
str.isupper に同じ |
istitle() |
str.istitle に同じ |
isnumeric() |
str.isnumeric に同じ |
isdecimal() |
str.isdecimal に同じ |