【Python入門】文字列の部分一致による抽出(query関数)

query-str pandas

条件に合ったデータの行を抽出する方法です。
文字列の「一部分と一致する」行の抽出は、pandasの文字列メソッドを使います。

query関数の使い方や、文字列に「完全に一致する」行の抽出は、以下をご確認ください。
【Python入門】条件指定による抽出(query関数のまとめ)

query関数を使用すると、すっきりとした条件式で抽出ができます。

サンプルデータ

説明に使用するデータを作成します。
pandas.DataFrameに、5行×4列の配列で、値を設定します。

列名データ型
val整数
name文字列
date日付型
regex特殊文字を含む文字列
import pandas as pd
df_sample = pd.DataFrame({'val': [10,20,30,20,50],
                          'name': ['ABC', 'BCD', 'CDE', 'EDC', 'CBA'],
                          'date': ['2019/1/1', '2019/2/16', '2019/3/10', '2019/3/31', '2019/5/1'],
                          'regex': ['test.txt', 'dog.jpg', 'Why?', '***', 'How?']})
# 文字列の「date]を、datetime64型に変換
df_sample['date'] = pd.to_datetime(df_sample['date'])
df_sample.head()
        val	name	date	        regex
0	10	ABC	2019-01-01	test.txt
1	20	BCD	2019-02-16	dog.jpg
2	30	CDE	2019-03-10	Why?
3	20	EDC	2019-03-31	***
4	50	CBA	2019-05-01	How?

文字列の部分一致による抽出

文字列の「一部分と一致する」行を抽出します。
pandasの文字列メソッドを使って、抽出の対象とする列の文字列のどの部分にある文字列と一致しているか確認します。

  • 前方一致: str.startswith()
  • 後方一致: str.endswith()
  • 部分一致: str.contains()
  • 正規表現: str.match()

正規表現は、前方一致や後方一致などの文字列を表現できる表記法です。
以下のような特殊文字を使用します。

特殊文字使い方備考
.任意の1文字
*直前の文字の0回以上の繰り返し
^文字列の先頭位置指定子
$文字列の末尾位置指定子

前方一致(特定の文字列で始まる)

列の要素が、特定の文字列で始まる行を抽出します。
文字列メソッド: str.startswith() を使用します。
引数のengine=’python’は、デフォルトでエラーがでるときは付けてください。

df_sample.query('name.str.startswith("C")', engine='python')
        val	name	date    	regex
2	30	CDE	2019-03-10	Why?
4	50	CBA	2019-05-01	How?

列名「name」が、文字列「C」で始まる行を抽出しました。

正規表現では、次のようになります。

df_sample.query('name.str.match("^C")', engine='python')
        val	name	date    	regex
2	30	CDE	2019-03-10	Why?
4	50	CBA	2019-05-01	How?

文字列の最初にマッチさせるため、位置指定子「^」で文字列の先頭を指定しています。

後方一致 (特定の文字列で終わる)

列の要素が、特定の文字列で終わる行を抽出します。
文字列メソッド: str.endswith() を使用します。

df_sample.query('name.str.endswith("C")', engine='python')
        val	name	date	        regex
0	10	ABC	2019-01-01	test.txt
3	20	EDC	2019-03-31	***

列名「name」が、文字列「C」で終わる行を抽出しました。

正規表現では、次のようになります。

df_sample.query('name.str.match(".*C$")', engine='python')
        val	name	date	        regex
0	10	ABC	2019-01-01	test.txt
3	20	EDC	2019-03-31	***

文字列の最後にマッチさせるため、位置指定子「$」で文字列の末尾を指定しています。
文字列「C」の前にある「.*」は、任意の1文字「.」が、0回以上の繰り返し「*」していることを表現しています。
これは、文字列「C」の前に、任意の文字列があっても、なくてもどちらでもよいが、文字列の最後の文字が「C」であることを意味しています。

部分一致(特定の文字列を含む)

列の要素が、特定の文字列を含む行を抽出します。
文字列メソッド: str. contains() を使用します。

df_sample.query('name.str.contains("C")', engine='python')
        val	name	date     	regex
0	10	ABC	2019-01-01	test.txt
1	20	BCD	2019-02-16	dog.jpg
2	30	CDE	2019-03-10	Why?
3	20	EDC	2019-03-31	***
4	50	CBA	2019-05-01	How?

列名「name」が、文字列「C」を含む行を抽出しました。

正規表現では、次のようになります。

df_sample.query('name.str.match(".*C")', engine='python')
        val	name	date     	regex
0	10	ABC	2019-01-01	test.txt
1	20	BCD	2019-02-16	dog.jpg
2	30	CDE	2019-03-10	Why?
3	20	EDC	2019-03-31	***
4	50	CBA	2019-05-01	How?

後方一致の例から、位置指定子「$」を除いた表現となっています。
文字列「C」の前に、任意の文字列があっても、なくてもどちらでもよいが、文字列「C」が含まれていると抽出されます。
文字列「C」が含まれていた時点で抽出されるので、文字列「C」より後ろの文字列は評価していません。

正規表現で使用する特殊文字の注意点

正規表現で使用する特殊文字を指定して抽出すると、特殊文字が意味する行がされるので注意が必要です。
列名「regex」が、 特殊文字「.」を含む行を抽出してみます。

df_sample.query('regex.str.contains(".")', engine='python')
        val	name	date     	regex
0	10	ABC	2019-01-01	test.txt
1	20	BCD	2019-02-16	dog.jpg
2	30	CDE	2019-03-10	Why?
3	20	EDC	2019-03-31	***
4	50	CBA	2019-05-01	How?

列名「regex」が、特殊文字「.」が意味する「任意の1文字」を含む行が抽出されました。

文字列「.」を含む行を抽出するときは、 特殊文字をエスケープするバックスラッシュ「\」を使用します。
(バックスラッシュは、Windows環境だと円マーク「\」として表示されます。)

df_sample.query('regex.str.contains("\.")', engine='python')
        val	name	date     	regex
0	10	ABC	2019-01-01	test.txt
1	20	BCD	2019-02-16	dog.jpg

列名「regex」が、文字列「.」を含む行が抽出できました。
同じように、特殊文字「?」や「*」の前に、「\」を使用すればよいです。

日付の指定による抽出

日付の一部が一致している行を抽出します。
(例: 3月、月の後半(16日以降)など)
日付の年月日などをpandasのdtアクセサで指定します。

  • 年: dt.year
  • 月: dt.month
  • 日: dt.day

列名「date」の日付が、3月の行を抽出します。

df_sample.query('date.dt.month == 3')
    val	name	date   	regex
2	30	CDE	2019-03-10	Why?
3	20	EDC	2019-03-31	***


列名「date」の日付が、16日以降の行を抽出します。

df_sample.query('date.dt.day >= 16')
        val	name	date     	regex
1	20	BCD	2019-02-16	dog.jpg
3	20	EDC	2019-03-31	***

まとめ

  • query関数を使用して、pandas.DataFrameから部分一致する行を抽出できました
  • 条件式を正規表現で記述できました
  • 日付の一部が一致している行を抽出できました

query関数を使用すると、簡潔に抽出条件が記述できるので、複数の条件指定をしても可読性が高いです。
完全一致と部分一致を組み合わせたり、否定との組み合わせなど、いろいろ試してみてください。

関連情報

タイトルとURLをコピーしました