88941


**やりたいこと**  
pythonで２つのエクセルを結合させたいです。  
両方のエクセルのキーとなるものは`title` になります。

実現したい結果のように  
sample_countryのエクセル`messageId`が入っている値を  
countryの`messageId`エクセルへ貼り付けたいです。

**sample_countryエクセル**  
※アメリカのようにtitleは重複する時があります。

createdAt | title | messageId  
---|---|---  
2020/5/20 | イギリス | 2276890175  
2020/5/20 | アメリカ | 2276890177  
2020/5/20 | アメリカ＞ニューヨーク | 2276891330  
2020/5/20 | スペイン | 2276891991  
2020/5/20 | アメリカ | 2276891992  
2020/5/20 | 日本 | 2276891993  
  
**countryエクセル**  
messageIdを貼り付けたいエクセル  
messageIdは空白になっております。  
sample_countryエクセルとtitleしか一致しないです。

No | title | messageId  
---|---|---  
1879 | アメリカ |  
1829 | アメリカ＞ニューヨーク |  
1209 | スペイン |  
1029 | アメリカ |  
  
**実現したいエクセルの結果**  
titleが一致するものに対してmessageIdを貼り付けたいです。

No | title | messageId  
---|---|---  
1879 | アメリカ | 2276890177  
1829 | アメリカ＞ニューヨーク | 2276891330  
1209 | スペイン | 2276891991  
1029 | アメリカ | 2276891992  
  
**現在の結果**  
titleが一致するものに対してmessageIdを貼り付ける事ができていますが、  
実現したい結果処理が上手く行かず、`messageId_x、messageId_y`の不要なセルが追加されます。  
またアメリカのタイトル何度も重複されます。

No | title | messageId_x | createdAt | messageId_y  
---|---|---|---|---  
1879 | アメリカ |  | 2020-05-20 00:00:00 | 2276890177  
1879 | アメリカ |  | 2020-05-20 00:00:00 | 2276891992  
1029 | アメリカ |  | 2020-05-20 00:00:00 | 2276890177  
1029 | アメリカ |  | 2020-05-20 00:00:00 | 2276891992  
1829 | アメリカ＞ニューヨーク |  | 2020-05-20 00:00:00 | 2276891330  
1829 | スペイン |  | 2020-05-20 00:00:00 | 2276891991  
  
全体コード

[code]

    import pandas as pd
     
    #sample_countryエクセル
    df1 = pd.read_excel("C:\\Users\\test\\Desktop\\sample_country.xlsx")
    #countryエクセル
    df2 = pd.read_excel("C:\\Users\\test\\Desktop\\country.xlsx")
    
    #Joinでtitleをキーにしてcountryエクセルへ貼り付ける
    df_inner_join = pd.merge(df2,df1,on='title',how='inner')
    #print(df_inner_join)
    
    #xlsx書き出し
    df_inner_join.to_excel("C:\\Users\\test\\Desktop\\country.xlsx", sheet_name="Sheet1", index=False, header=True)
    
    
[/code]

すいませんがPandasのjoinについてまだ勉強中です。  
別の方法でも結合あれば、教えていただけると嬉しいです。

お手数ですが、よろしくお願い致します。


CC BY-SA 4.0
2022-05-20T06:03:43.740
88935
2022-05-25T05:51:23.577
2022-05-20T06:12:48.640
18859
18859
question
python python3
pythonで Pandasを使ってエクセルを結合させる方法


Python, Pandas は詳しくないのであくまで考え方のみ回答します。

* * *

私なら「表の結合」ではなく、以下のような手順を踏むと思います。

  * まずsample_country から `title` をキー、`messageId` を値にした辞書を作成
  * country に対して先ほど作成した辞書を元に、該当する `messageId` を埋めていく

※「アメリカのように title は重複する時がある」と書かれていますが、実際に重複した場合にどう処理するのかが
([関連質問のコメント](https://ja.stackoverflow.com/questions/88876/python%e3%81%a7excel%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%81%ab%e7%89%b9%e5%ae%9a%e3%81%ae%e8%a1%8c%e3%82%92%e6%9b%b8%e3%81%8d%e8%be%bc%e3%81%bf%e3%81%97%e3%81%9f%e3%81%84#comment100836_88876)
でも指摘しましたが) 明言されていないので考慮していません。


CC BY-SA 4.0
2022-05-20T08:04:50.277
88938
2022-05-20T08:04:50.277
3060
88935
answer


前回 [PythonでExcelファイルに特定の行を書き込みしたい](https://ja.stackoverflow.com/q/88876/26370)
同様に、「excelの中でtitleが合っていてmessageIdの空いている所を上から順番に埋めていく。excelに合うtitleが無ければ何もしない」という緩い仕様で考えて回答を作成しました。

両方のExcelを読み取り後の処理が以下になります。  
`df1`から`title`と`messageId`の列だけ抽出して2次元のリストにしてから、前回の回答と同様の処理を行っています。  
既に2次元のリストにしているので、zip処理は無しです。

[code]

    df1_list = df1[['title', 'messageId']].values.tolist()
    print(df1_list)
    
    for curtitle, curmsgid in df1_list:
        wdf = df2.query('(title == @curtitle) and (`messageId` != `messageId`)')
        if len(wdf) <= 0: continue
        df2.at[wdf.index[0], 'messageId'] = curmsgid
    
    #xlsx書き出し
    df2.to_excel("C:\\Users\\test\\Desktop\\country.xlsx", sheet_name="Sheet1", index=False, header=True)
    
[/code]


CC BY-SA 4.0
2022-05-20T09:44:36.890
88941
2022-05-20T09:53:23.583
2022-05-20T09:53:23.583
26370
26370
88935
answer


(エクセル関係ない気がするけど)

[pandas.merge](https://pandas.pydata.org/docs/reference/api/pandas.merge.html)
は参照先によると (SQL) "database-style join" ということです。  
なので, たとえば [sqlite3 --- SQLite データベースに対する DB-API 2.0
インターフェース](https://docs.python.org/ja/3/library/sqlite3.html) などが 動作の参考になるかも

(一例としてあげると)
「顧客の購買情報テーブル」と「顧客情報テーブル」を「顧客ID」で関連付けるなどがイメージしやすい…のかも。購買情報が複数あっても大丈夫だけど, 顧客情報に
同じ顧客IDで 2件の情報が登録されてれば, 結果は二倍に

`country` 側の項目 `No` の意味が不明だけれど, それを無視してよいなら(重複取り除いて)以下のように

[code]

    df2_nodup = df2.drop_duplicates(subset='title')
    df = pd.merge(df2_nodup, df1, on='title', how='inner').drop(columns='createdAt')
    
[/code]

(データベースのように扱うのなら, "東日本", "西日本" などのように何か区別できるような持ち方しないとマッチできない)

`No` に何か意味があり上から順に割り当てるのなら `pandas.merge`は向かないかも

[code]

    df = df2.copy()
    df.messageId = df2.groupby(by='title').apply(lambda subf:
            df1.messageId[df1.title == subf.name].set_axis(subf.index)
        ).droplevel(0)
    display(df)
    
[/code]


CC BY-SA 4.0
2022-05-25T03:56:35.920
89037
2022-05-25T05:51:23.577
2022-05-25T05:51:23.577
43025
43025
88935
answer