💭

[Python]Pandasを使ってCSVのデータを結合する

2021/05/02に公開1

CSV同士で RDBのような結合をしたい

CSVでRDBのテーブル結合のようなことをしたい!ということで今回の記事を書きました。

何か複数のレポートデータを結合したい時とかに便利なのではないでしょうか?

インストール

$ pip install pandas

今回はpandasを使います。そもそもpandasが入ってない方はこちらから

CSVの内容

今回対象にするCSVはこちら。

students.csv
ID,名前,年齢,学校ID
1,山田,15,3
2,佐藤,13,1
3,石田,14,3
4,榊原,14,5
5,五十嵐,12,2
universities.csv
ID,学校名
1,東京大学
2,京都大学
3,名古屋大学
4,神戸大学

内部結合(INNER JOIN)

方法その1

merge.py
import pandas as pd

# まず2つのCSVを読み込む
df = pd.read_csv('./students.csv', encoding='utf-8')
df2 = pd.read_csv('./universities.csv', encoding='utf-8')

# universitiesのIDを学校IDという名前に変更する
df2_ = df2.rename(columns={'ID': '学校ID'})

# 学校IDというキーを元にして2つのCSVを結合する
df_merged = pd.merge(df, df2_, on='学校ID'))

df_merged.to_csv("merged.csv", index=False)
出力結果
   ID   名前  年齢  学校ID    学校名
0   1   山田  15     3  名古屋大学
1   3   石田  14     3  名古屋大学
2   2   佐藤  13     1   東京大学
3   5  五十嵐  12     2   京都大学
merged.csv
ID,名前,年齢,学校ID,学校名
1,山田,15,3,名古屋大学
3,石田,14,3,名古屋大学
2,佐藤,13,1,東京大学
5,五十嵐,12,2,京都大学

出力結果を見ればわかりますが、内部結合になっています。
榊原さんに対応する学校がなかったので、その榊原さんの行がなくってしまいましたね。神戸大学もまた然りです。
また、mergeは同じ列名をキーにするようなので、途中でdf2のIDを学校IDに変更して名前を統一しました。

方法その2

merge.py
import pandas as pd

# まず2つのCSVを読み込む
df = pd.read_csv('./students.csv', encoding='utf-8')
df2 = pd.read_csv('./universities.csv', encoding='utf-8')

# dfは学校IDをキーに、df2はIDをキーに内部結合
df_merged = pd.merge(df, df2, left_on='学校ID', right_on='ID')

print(df_merged)
出力結果
   ID_x   名前  年齢  学校ID  ID_y    学校名
0     1   山田  15     3     3  名古屋大学
1     3   石田  14     3     3  名古屋大学
2     2   佐藤  13     1     1   東京大学
3     5  五十嵐  12     2     2   京都大学

結合するときキーを個別に指定できるのだけど出力結果が気にいらない。一応覚えておこう。

外部結合(OUTER JOIN)

merge.py
import pandas as pd

# まず2つのCSVを読み込む
df = pd.read_csv('./students.csv', encoding='utf-8')
df2 = pd.read_csv('./universities.csv', encoding='utf-8')

# how='outer'を指定
df_merged = pd.merge(df, df2_, on='学校ID', how='outer')

print(df_merged)

df_merged.to_csv("merged.csv", index=False)
出力結果
    ID   名前    年齢  学校ID    学校名
0  1.0   山田  15.0     3  名古屋大学
1  3.0   石田  14.0     3  名古屋大学
2  2.0   佐藤  13.0     1   東京大学
3  4.0   榊原  14.0     5    NaN
4  5.0  五十嵐  12.0     2   京都大学
5  NaN  NaN   NaN     4   神戸大学
merged.csv
ID,名前,年齢,学校ID,学校名
1.0,山田,15.0,3,名古屋大学
3.0,石田,14.0,3,名古屋大学
2.0,佐藤,13.0,1,東京大学
4.0,榊原,14.0,5,
5.0,五十嵐,12.0,2,京都大学
,,,4,神戸大学

なぜかIDが少数になった!原因は不明。
外部結合なので、さっき結合先がいなかった榊原さんと神戸大学が表に現れました。

左外部結合(LEFT OUTER JOIN)

merge.py
import pandas as pd

# まず2つのCSVを読み込む
df = pd.read_csv('./students.csv', encoding='utf-8')
df2 = pd.read_csv('./universities.csv', encoding='utf-8')

# how='left'を指定
df_merged = pd.merge(df, df2_, on='学校ID', how='left')

print(df_merged)

df_merged.to_csv("merged.csv", index=False)
出力結果
   ID   名前  年齢  学校ID    学校名
0   1   山田  15     3  名古屋大学
1   2   佐藤  13     1   東京大学
2   3   石田  14     3  名古屋大学
3   4   榊原  14     5    NaN
4   5  五十嵐  12     2   京都大学
merged.csv
ID,名前,年齢,学校ID,学校名
1,山田,15,3,名古屋大学
2,佐藤,13,1,東京大学
3,石田,14,3,名古屋大学
4,榊原,14,5,
5,五十嵐,12,2,京都大学

左外部結合なので榊原さんがの大学がNaNとして表に現れる

右外部結合(RIGHT OUTER JOIN)

merge.py
import pandas as pd

# まず2つのCSVを読み込む
df = pd.read_csv('./students.csv', encoding='utf-8')
df2 = pd.read_csv('./universities.csv', encoding='utf-8')

# how='right'を指定
df_merged = pd.merge(df, df2_, on='学校ID', how='right')

print(df_merged)

df_merged.to_csv("merged.csv", index=False)
出力結果
    ID   名前    年齢  学校ID    学校名
0  1.0   山田  15.0     3  名古屋大学
1  3.0   石田  14.0     3  名古屋大学
2  2.0   佐藤  13.0     1   東京大学
3  5.0  五十嵐  12.0     2   京都大学
4  NaN  NaN   NaN     4   神戸大学
merged.csv
ID,名前,年齢,学校ID,学校名
1.0,山田,15.0,3,名古屋大学
3.0,石田,14.0,3,名古屋大学
2.0,佐藤,13.0,1,東京大学
5.0,五十嵐,12.0,2,京都大学
,,,4,神戸大学

これまたIDが少数になった!原因は不明。(きっと理解不足)
こちらは右外部結合なので、相方が不在の神戸大学に対応する部分はNaNになる。

結論

DataFrameをテーブルのように結合する時は、mergeメソッドにキーワード引数howに対して、outer,left,rightを入れればOK

Discussion

sumitosumito

参考になりましたありがとうございます。

df_merged = pd.merge(df, df2_, on='学校ID'))

この部分ですが、閉じカッコが一つ多いと思います。