pandas.DataFrame, Seriesを連結するconcat

Modified: | Tags: Python, pandas

複数のpandas.DataFrame, pandas.Seriesを連結(結合)するpandas.concat()関数の使い方について説明する。

新たな行や列を追加するにはconcat()よりもその他の方法のほうが簡単な場合がある。詳細は以下の記事を参照。

共通のデータ列を持つ複数のpandas.DataFrameをその列の値に従って結合するにはpandas.merge()関数またはpandas.DataFramemerge()メソッドを使う。

本記事のサンプルコードのpandasのバージョンは以下の通り。バージョンによって仕様が異なる可能性があるので注意。以下のpandas.DataFrameおよびpandas.Seriesを例とする。

import pandas as pd

print(pd.__version__)
# 2.0.3

df1 = pd.DataFrame({'A': ['A1', 'A2', 'A3'],
                    'B': ['B1', 'B2', 'B3'],
                    'C': ['C1', 'C2', 'C3']},
                   index=['ONE', 'TWO', 'THREE'])
print(df1)
#         A   B   C
# ONE    A1  B1  C1
# TWO    A2  B2  C2
# THREE  A3  B3  C3

df2 = pd.DataFrame({'C': ['C2', 'C3', 'C4'],
                    'D': ['D2', 'D3', 'D4']},
                   index=['TWO', 'THREE', 'FOUR'])
print(df2)
#         C   D
# TWO    C2  D2
# THREE  C3  D3
# FOUR   C4  D4

s1 = pd.Series(['X1', 'X2', 'X3'], index=['ONE', 'TWO', 'THREE'], name='X')
print(s1)
# ONE      X1
# TWO      X2
# THREE    X3
# Name: X, dtype: object

s2 = pd.Series(['Y2', 'Y3', 'Y4'], index=['TWO', 'THREE', 'FOUR'], name='Y')
print(s2)
# TWO      Y2
# THREE    Y3
# FOUR     Y4
# Name: Y, dtype: object

pandas.concat()の基本的な使い方

連結するオブジェクトを指定: 引数objs

第一引数objsに、連結するpandas.DataFrame, pandas.Seriesをリストやタプルで指定する。pandas.Seriesの例は後述。

df_concat = pd.concat([df1, df2])
print(df_concat)
#          A    B   C    D
# ONE     A1   B1  C1  NaN
# TWO     A2   B2  C2  NaN
# THREE   A3   B3  C3  NaN
# TWO    NaN  NaN  C2   D2
# THREE  NaN  NaN  C3   D3
# FOUR   NaN  NaN  C4   D4

連結するオブジェクトの個数は3個以上でもよい。

df_concat_multi = pd.concat([df1, df2, df1])
print(df_concat_multi)
#          A    B   C    D
# ONE     A1   B1  C1  NaN
# TWO     A2   B2  C2  NaN
# THREE   A3   B3  C3  NaN
# TWO    NaN  NaN  C2   D2
# THREE  NaN  NaN  C3   D3
# FOUR   NaN  NaN  C4   D4
# ONE     A1   B1  C1  NaN
# TWO     A2   B2  C2  NaN
# THREE   A3   B3  C3  NaN

新たなオブジェクトが生成され、元のオブジェクトは変更されない。

連結方向(縦・横)の指定: 引数axis

縦・横どちらの方向に連結するかは引数axisで指定する。

axis=0とすると縦方向に連結される。これがデフォルトなので省略しても同じ。

df_v = pd.concat([df1, df2], axis=0)
print(df_v)
#          A    B   C    D
# ONE     A1   B1  C1  NaN
# TWO     A2   B2  C2  NaN
# THREE   A3   B3  C3  NaN
# TWO    NaN  NaN  C2   D2
# THREE  NaN  NaN  C3   D3
# FOUR   NaN  NaN  C4   D4

axis=1とすると横方向に連結される。

df_h = pd.concat([df1, df2], axis=1)
print(df_h)
#          A    B    C    C    D
# ONE     A1   B1   C1  NaN  NaN
# TWO     A2   B2   C2   C2   D2
# THREE   A3   B3   C3   C3   D3
# FOUR   NaN  NaN  NaN   C4   D4

連結方法(外部結合・内部結合)の指定: 引数join

連結した結果、すべての列・行を残すか、共通する名前の列・行のみを残すかを引数joinで指定する。

join='outer'は外部結合。すべての列・行が残る。これがデフォルトなので省略しても同じ。この場合、元のオブジェクトに存在しない列・行の要素は欠損値NaNとなる。

join='inner'は内部結合。共通の名前の列・行のみが残る。

df_v_out = pd.concat([df1, df2], join='outer')
print(df_v_out)
#          A    B   C    D
# ONE     A1   B1  C1  NaN
# TWO     A2   B2  C2  NaN
# THREE   A3   B3  C3  NaN
# TWO    NaN  NaN  C2   D2
# THREE  NaN  NaN  C3   D3
# FOUR   NaN  NaN  C4   D4

df_v_in = pd.concat([df1, df2], join='inner')
print(df_v_in)
#         C
# ONE    C1
# TWO    C2
# THREE  C3
# TWO    C2
# THREE  C3
# FOUR   C4

横方向(axis=1)でも同じ。

df_h_out = pd.concat([df1, df2], axis=1, join='outer')
print(df_h_out)
#          A    B    C    C    D
# ONE     A1   B1   C1  NaN  NaN
# TWO     A2   B2   C2   C2   D2
# THREE   A3   B3   C3   C3   D3
# FOUR   NaN  NaN  NaN   C4   D4

df_h_in = pd.concat([df1, df2], axis=1, join='inner')
print(df_h_in)
#         A   B   C   C   D
# TWO    A2  B2  C2  C2  D2
# THREE  A3  B3  C3  C3  D3

連結する列や行を制御するには、列名columnsや行名indexを変更すればよい。rename()set_axis()メソッドなどを使う。

df_h = pd.concat([df1, df2.rename(index={'FOUR': 'ONE'})], axis=1)
print(df_h)
#         A   B   C   C   D
# ONE    A1  B1  C1  C4  D4
# TWO    A2  B2  C2  C2  D2
# THREE  A3  B3  C3  C3  D3

pandas.DataFrame同士の連結

これまでの例のように、pandas.DataFrame同士を連結するとpandas.DataFrameが返される。

df_concat = pd.concat([df1, df2])
print(df_concat)
#          A    B   C    D
# ONE     A1   B1  C1  NaN
# TWO     A2   B2  C2  NaN
# THREE   A3   B3  C3  NaN
# TWO    NaN  NaN  C2   D2
# THREE  NaN  NaN  C3   D3
# FOUR   NaN  NaN  C4   D4

print(type(df_concat))
# <class 'pandas.core.frame.DataFrame'>

pandas.Series同士の連結

pandas.Series同士の連結の場合、縦方向の連結(axis=0、デフォルト)ではpandas.Seriesが返される。

s_v = pd.concat([s1, s2])
print(s_v)
# ONE      X1
# TWO      X2
# THREE    X3
# TWO      Y2
# THREE    Y3
# FOUR     Y4
# dtype: object

print(type(s_v))
# <class 'pandas.core.series.Series'>

横方向の連結(axis=1)ではpandas.DataFrameが返される。引数joinも使える。

s_h = pd.concat([s1, s2], axis=1)
print(s_h)
#          X    Y
# ONE     X1  NaN
# TWO     X2   Y2
# THREE   X3   Y3
# FOUR   NaN   Y4

print(type(s_h))
# <class 'pandas.core.frame.DataFrame'>
s_h_in = pd.concat([s1, s2], axis=1, join='inner')
print(s_h_in)
#         X   Y
# TWO    X2  Y2
# THREE  X3  Y3

コンストラクタpandas.DataFrame()を利用して複数のSeriesからDataFrameを生成する方法もある。この場合、Seriesを行としてDataFrameにすることもできる。以下の記事を参照。

pandas.DataFrameとpandas.Seriesの連結

pandas.DataFramepandas.Seriesの連結の場合、横方向の連結(axis=1)ではpandas.Seriesが新たな列として追加される。pandas.Seriesnameが列名となる。引数joinも使える。

df_s_h = pd.concat([df1, s2], axis=1)
print(df_s_h)
#          A    B    C    Y
# ONE     A1   B1   C1  NaN
# TWO     A2   B2   C2   Y2
# THREE   A3   B3   C3   Y3
# FOUR   NaN  NaN  NaN   Y4

df_s_h_in = pd.concat([df1, s2], axis=1, join='inner')
print(df_s_h_in)
#         A   B   C   Y
# TWO    A2  B2  C2  Y2
# THREE  A3  B3  C3  Y3

縦方向の連結(axis=0、デフォルト)では以下のような結果となる。

df_s_v = pd.concat([df1, s1])
print(df_s_v)
#          A    B    C    0
# ONE     A1   B1   C1  NaN
# TWO     A2   B2   C2  NaN
# THREE   A3   B3   C3  NaN
# ONE    NaN  NaN  NaN   X1
# TWO    NaN  NaN  NaN   X2
# THREE  NaN  NaN  NaN   X3

pandas.Seriesを新たな行として追加するには、pandas.Seriespandas.DataFrameに変換して連結するか、.locを使う。

print(s1.set_axis(df1.columns).to_frame().T)
#     A   B   C
# X  X1  X2  X3

df_s_v = pd.concat([df1, s1.set_axis(df1.columns).to_frame().T])
print(df_s_v)
#         A   B   C
# ONE    A1  B1  C1
# TWO    A2  B2  C2
# THREE  A3  B3  C3
# X      X1  X2  X3
print(s2.values)
# ['Y2' 'Y3' 'Y4']

df1.loc[s2.name] = s2.values
print(df1)
#         A   B   C
# ONE    A1  B1  C1
# TWO    A2  B2  C2
# THREE  A3  B3  C3
# Y      Y2  Y3  Y4

関連カテゴリー

関連記事