Python学習チャンネル by PyQ

Pythonのオンライン学習プラットフォームPyQのオフィシャルブログです

「pandasで、A列からB列の文字を除いた列Cを作成するには?」applyを使った効率的な処理方法

f:id:nana_yu:20190131133642p:plain

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で下記のパートやクエストで学習できます。

Copyright ©2017-2019 BeProud Inc. All rights reserved.