pandasのSeriesやDataFrameを連結する方法について解説します。
Contents
SeriesやDataFrameの連結方法
データ分析の際には、異なる種類のデータソースの組み合わせから深い知見や研究成果が得られるということがほとんどです。ここでいう「組み合わせ」とは2つのデータセットを単に連結するだけではなく、重複するデータを適切に処理することも含まれます。
pandasで中心的なデータ構造はSeriesやDataFrameです。これらは連結処理を念頭に置いて設計されているため、データを簡単に連結することができます。具体的には、pandasのSeriesやDataFrameを連結したい場合、concat
関数を使用することができます。
この記事では、pandasのconcat
関数を用いたデータの連結方法を説明します。
concat関数の基本的な使い方
SeriesやDataFrameを連結する場合にはconcat
関数を使用します。以下の簡単な例を見てみましょう。
import pandas as pd # ===== Seriesの連結 # データの準備 ser1 = pd.Series(['A', 'B', 'C', 'D', 'E'], index=[1, 2, 3, 4, 5]) ser2 = pd.Series(['V', 'W', 'X', 'Y', 'Z'], index=[6, 7, 8, 9, 10]) # 連結 ser_concat = pd.concat([ser1, ser2]) print(ser_concat, '\n') # ===== DataFrameの連結 # データの準備 df1 = pd.DataFrame([['A', 'B'], ['C', 'D'], ['E', 'F']], index=[1, 2, 3], columns=['attr1', 'attr2']) df2 = pd.DataFrame([['U', 'V'], ['W', 'X'], ['Y', 'Z']], index=[4, 5, 6], columns=['attr1', 'attr2']) # 連結 df_concat = pd.concat([df1, df2]) print(df_concat)
【実行結果】 1 A 2 B 3 C 4 D 5 E 6 V 7 W 8 X 9 Y 10 Z dtype: object attr1 attr2 1 A B 2 C D 3 E F 4 U V 5 W X 6 Y Z
上記では、SeriesとDataFrameをそれぞれ連結をしています。使用方法は簡単で、concat
関数の引数に連結したい対象のSeriesやDataFrameを含むリストを指定するだけです。
インデックスが重複している場合
concat
関数の特徴として、連結するデータのインデックスが重複していても、それぞれのインデックスが保持される点があります。以下は、インデックス2, 3が重複しているケースです。
import pandas as pd # ===== DataFrameの連結 # データの準備 df1 = pd.DataFrame([['A', 'B'], ['C', 'D'], ['E', 'F']], index=[1, 2, 3], columns=['attr1', 'attr2']) df2 = pd.DataFrame([['U', 'V'], ['W', 'X'], ['Y', 'Z']], index=[2, 3, 4], columns=['attr1', 'attr2']) # 連結 (インデックスが重複していても保持する) df_concat = pd.concat([df1, df2]) print(df_concat)
【実行結果】 attr1 attr2 1 A B 2 C D 3 E F 2 U V 3 W X 4 Y Z
上記結果を見ると、インデックス2, 3が複数回出現していることが分かります。
このような状況でも問題がなければそのままで構いません。もし、重複が問題になる場合は、後述するverify_integrity
やignore_index
を使った対処法があります。
重複がある場合に例外を出す ~ verify_integrity ~
concat
関数は、インデックスが重複していても保持します。インデックスの重複が問題になる場合、重複があることを例外として出して対処する方法があります。
重複した場合に例外を出すには、以下のようにverify_integrity
をTrue
に設定します。
import pandas as pd # ===== DataFrameの連結 df1 = pd.DataFrame([['A', 'B'], ['C', 'D'], ['E', 'F']], index=[1, 2, 3], columns=['attr1', 'attr2']) df2 = pd.DataFrame([['U', 'V'], ['W', 'X'], ['Y', 'Z']], index=[2, 3, 4], columns=['attr1', 'attr2']) # 連結 (インデックス重複時は例外:ValueError) try: df_concat = pd.concat([df1, df2], verify_integrity=True) print(df_concat) except ValueError as ex: print(ex)
【実行結果】 Indexes have overlapping values: Int64Index([2, 3], dtype='int64')
verify_integrity
をTrue
に設定すると、インデックスが重複していた場合には、ValueError
の例外が発生します。この例外をキャッチすることで、処理を変更することが可能です。
インデックスを無視する ~ ignore_index ~
インデックスが重複しているケースで、もともとのインデックスが意味を持たない場合は、インデックスを無視して新しいインデックスを振ることが可能です。
インデックスを無視して新しいインデックスを振るには、以下のようにignore_index
をTrueに設定します。
import pandas as pd # ===== DataFrameの連結 df1 = pd.DataFrame([['A', 'B'], ['C', 'D'], ['E', 'F']], index=[1, 2, 3], columns=['attr1', 'attr2']) df2 = pd.DataFrame([['U', 'V'], ['W', 'X'], ['Y', 'Z']], index=[2, 3, 4], columns=['attr1', 'attr2']) # 連結 (インデックスを無視する) df_concat = pd.concat([df1, df2], ignore_index=True) print(df_concat)
【実行結果】 attr1 attr2 0 A B 1 C D 2 E F 3 U V 4 W X 5 Y Z
上記結果から、もともとのインデックスが無視され、新しいインデックスが0から設定されてデータが結合されていることが分かります。
連結するデータにキーを指定して階層型インデックス(マルチインデックス)にする ~ keys ~
データを連結する際に、元のデータのキーを残して結合したい場合は、階層型インデックス(マルチインデックス)を使用して対応することができます。階層型インデックスにするには、以下のようにkeys
で各データのキー情報を指定します。
import pandas as pd # ===== DataFrameの連結 # データの準備 df1 = pd.DataFrame([['A', 'B'], ['C', 'D'], ['E', 'F']], index=[1, 2, 3], columns=['attr1', 'attr2']) df2 = pd.DataFrame([['U', 'V'], ['W', 'X'], ['Y', 'Z']], index=[2, 3, 4], columns=['attr1', 'attr2']) # 連結 (階層型のインデックスにする) df_concat = pd.concat([df1, df2], keys=['D1', 'D2']) print(df_concat)
【実行結果】 attr1 attr2 D1 1 A B 2 C D 3 E F D2 2 U V 3 W X 4 Y Z
上記の例では"D1"
、"D2"
を指定しています。結果として、それぞれのキーの下に元のデータのインデックスが階層型インデックスとして配置され、データが連結されています。
積集合での連結 ~ join=”inner” ~
上記で見てきた例では、列名が全く同じデータを連結してきました。では、列名が異なるデータを連結する場合はどうなるでしょうか。以下の例で見てみましょう。
import pandas as pd # ===== DataFrameの連結 df1 = pd.DataFrame([['A', 'B'], ['C', 'D'], ['E', 'F']], index=[1, 2, 3], columns=['attr1', 'attr2']) df2 = pd.DataFrame([['U', 'V'], ['W', 'X'], ['Y', 'Z']], index=[4, 5, 6], columns=['attr2', 'attr3']) # 連結 (デフォルトはjoin='outer') df_concat = pd.concat([df1, df2]) print(df_concat, '\n') # 連結 (join='inner') df_concat = pd.concat([df1, df2], join='inner') print(df_concat)
【実行結果】 attr1 attr2 attr3 1 A B NaN 2 C D NaN 3 E F NaN 4 NaN U V 5 NaN W X 6 NaN Y Z attr2 1 B 2 D 3 F 4 U 5 W 6 Y
concat関数は、デフォルトではjoin="outer"
となっています。outer
は和集合を意味し、両方の列を含んだ連結が行われ、値がない部分は上記結果のようにNaN
となります。
もし、それぞれのデータセットに存在する列のみを連結したい場合は、join="inner"
を指定します。これにより積集合としての連結が行われます。上記結果を見ると、join="inner"
を指定した場合は、両方に存在する"attr2"
列のみ連結したデータが得られていることが分かります。
concat関数の公式ドキュメントはこちらを参照してください。
appendメソッドによるデータ連結【非推奨】
appendメソッドは、1.4.0から非推奨になっており、将来的にはpandasから削除される予定です。バージョンによってはconcat
関数を使用するよう警告が表示される場合があります。
append
メソッドは使用可能な場合であっても、データ連結の際はconcat
関数の使用を推奨します。
その他のデータの結合方法(merge, join)
上記では、concat
関数を用いた連結方法について紹介しました。pandasには、他にもmerge
関数やjoin
メソッドという強力なデータ結合方法があります。
データベースのSQLに慣れている人にとっては、merge
関数やjoin
メソッドが理解しやすいかもしれません。これらの使用方法については「DataFrameを結合する方法」でまとめていますので興味があれば参考にしてください。
まとめ
pandasのSeriesやDataFrameを連結する方法について解説しました。具体的には、concat
関数によるデータ連結方法について説明しました。
データ分析では、単にデータを連結するだけではなく、重複するデータの適切な処理や、連結時に元のデータを保持しながら階層型インデックス(マルチインデックス)を作成する方法、さらにouter
やinner
結合を使い分けることが重要です。これらについて本記事で紹介しました。
データ分析においては、複数のデータソースを適切に結合してから分析を行うことで、有益な情報を抽出できます。concat
関数を利用したデータ結合に慣れることは重要です。
上記で紹介しているソースコードについてはgithubにて公開しています。参考にしていただければと思います。