PyQ開発チームの斎藤です。 データ分析のライブラリーであるpandasは、非常に便利ですが、なかなか効率的な書き方がわからないことがあります。ここでは、PyQに来た質問を例にして紹介します。
質問
以下の表のA列からB列の文字を除いた列Cを作成するにはどうしたらいいでしょうか?
A | B | |
---|---|---|
0 | 桃 梨 林檎 | 梨 |
1 | イギリス フランス | フランス |
2 | 宮城 東京 沖縄 | 沖縄 |
列Aから固定の文字列を取り除くのであれば、strアクセサを使ってdf.A.str.replace(文字列, '')
のようにできますが、行ごとに除きたい文字列が異なる場合は、どうしたらいいでしょうか?
回答
for文を使って処理する
下記のようにすれば、やりたいことは可能です。
result = [] for row in df.itertuples(): result.append(row.A.replace(row.B, '')) df['C'] = result
apply
を使った効率的な書き方
しかし、for文を使うのは効率的ではありません。apply
を使うと効率的に書くことができます。
apply
を使うと、行または列に対して、一括処理を行えます。下記では、第2引数を1
としているので、行に対して処理しています。
df['C'] = df.apply(lambda row: row.A.replace(row.B, ''), 1)
除きたい行内の単語が複数の場合
では、除きたい単語が複数の場合は、どうしたらいいでしょうか? たとえば、下記のような場合、1行目は、「梨」または「なし」を削除したいとします。
A | B | |
---|---|---|
0 | 桃 梨 林檎 | 梨 なし |
1 | イギリス フランス | フランス France |
2 | 宮城 東京 沖縄 | 沖縄 Okinawa |
下記のように正規表現を使うとできます。
ここでは、f"({row.B.replace(' ', '|')})"
で'(梨|なし)'
のような正規表現を作成しています。この正規表現は、「梨」または「なし」を表しています。
import re df['C'] = df.apply(lambda row: re.sub(f"({row.B.replace(' ', '|')})", '', row.A), 1)
lambda式はちょっとした式を書くのには便利ですが、この場合は複雑なので、lambda式にしない方が良いでしょう。 次のように書けます。
def remove_from_A(row): return re.sub(f"({row.B.replace(' ', '|')})", '', row.A) df['C'] = df.apply(remove_from_A, 1)
なお、正規表現とstrアクセサは、PyQで下記のパートやクエストで学習できます。