質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.08%

pandas同士を前方一致させてマージする方法について

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 185

mi2

score 30

前提・実現したいこと

pandasの2つのデータフレームが、以下の例のように存在しています。

ここで、それぞれの2つのカラム名を閾値をもとに前方一致させ、それらをキーにしてデータをマージしたいと考えております。

インプットのデータフレームの例

df = 
name, size
犬Aの小さい個体の体長, 15
猫Aの小さい個体の体長, 13
金魚Aの体長, 1
犬Aの大きい個体の体長, 110
猫Aの大きい個体の体長, 100

master_df =
name, number_of_types
犬, 700
猫, 500
金魚, 100

アウトプットのデータフレームの例

output_df =
name, number_of_types
犬, 700, 犬Aの小さい個体の体長, 15
犬, 700, 犬Aの大きい個体の体長, 110
猫, 500, 猫Aの小さい個体の体長, 13
猫, 500, 猫Aの大さい個体の体長, 100
金魚, 100, 金魚Aの体長, 1

参考:エクセル上での抽出イメージ

前方一致検索でVLOOKUPを使うと出来ます。
このような内容をpythonで書きたいです。
https://office-hack.com/excel/vlookup-wildcard/

考えたこと

完全一致や部分一致で特定のdfから条件に合うものは、以下のように書けると思います。

df_master['name'] == '犬'
df['name'].str.contains('犬', na=False)

上記のような抽出のイメージはあるのですが、2つのpandasのデータフレーム上で検索して前方一致でマージする方法についてお知恵を拝借できましたら幸いです。
何卒よろしくお願い申し上げます。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

master_df['name'].apply(lambda n: df['name'].str.startswith(n)).idxmax()

にて対象となるデータフレームの Index値を得ることができるかと思いますので、あとは pandas.merge() すると良いかと思います。

import pandas as pd

df = pd.DataFrame({
    'name' : ['犬Aの小さい個体の体長', '猫Aの小さい個体の体長',
              '金魚Aの体長', '犬Aの大きい個体の体長', '猫Aの大きい個体の体長'],
    'size' : [15, 13, 1, 110, 100]})
master_df = pd.DataFrame({
    'name' : ['犬', '猫', '金魚'],
    'number_of_types' : [700, 500, 100]})

df['target'] = master_df['name'].apply(lambda n: df['name'].str.startswith(n)).idxmax()

ret = pd.merge(df, master_df, left_on='target', right_index=True, how='left').drop('target', axis=1)
#        name_x  size name_y  number_of_types
#0  犬Aの小さい個体の体長    15      犬              700
#1  猫Aの小さい個体の体長    13      猫              500
#2       金魚Aの体長     1     金魚              100
#3  犬Aの大きい個体の体長   110      犬              700
#4  猫Aの大きい個体の体長   100      猫              500

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

dfに別の列を作ってdfのnameにmaster_dfのnameが含まれていたら、
master_dfのnameを登録しておいてそれをキーとして利用する方法はどうでしょう。

import pandas as pd

df = pd.DataFrame(
    [['犬Aの小さい個体の体長', 15],
    ['猫Aの小さい個体の体長', 13],
    ['金魚Aの体長', 1],
    ['犬Aの大きい個体の体長', 110],
    ['猫Aの大きい個体の体長', 100]],
    columns=['name', 'size'])

master_df = pd.DataFrame(
    [['犬', 700],
    ['猫', 500],
    ['金魚', 100]],
    columns=['name', 'number_of_types'])

#master_dfのname列を繰り返し処理
for column_name, item in master_df.name.iteritems():
    #dfのnameにmaster_dfのnameが含まれる場合、master_dfのnameをdfのname_key列として追加
    df.loc[df.name.str.contains(item), 'name_key'] = item
print(df)
'''
          name  size name_key
0  犬Aの小さい個体の体長    15        犬
1  猫Aの小さい個体の体長    13        猫
2       金魚Aの体長     1       金魚
3  犬Aの大きい個体の体長   110        犬
4  猫Aの大きい個体の体長   100        猫
'''

#master_dfのname列とdfのname_key列で結合し、name_key列を削除
output_df = pd.merge(master_df, df, left_on='name', right_on='name_key', how='inner').drop("name_key", axis=1)
print(output_df)
'''
  name_x  number_of_types       name_y  size
0      犬              700  犬Aの小さい個体の体長    15
1      犬              700  犬Aの大きい個体の体長   110
2      猫              500  猫Aの小さい個体の体長    13
3      猫              500  猫Aの大きい個体の体長   100
4     金魚              100       金魚Aの体長     1
'''

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.08%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る