pandas.DataFrame, Seriesを連結するconcat
複数のpandas.DataFrame
, pandas.Series
を連結(結合)するpandas.concat()
関数の使い方について説明する。
新たな行や列を追加するにはconcat()
よりもその他の方法のほうが簡単な場合がある。詳細は以下の記事を参照。
共通のデータ列を持つ複数のpandas.DataFrame
をその列の値に従って結合するにはpandas.merge()
関数またはpandas.DataFrame
のmerge()
メソッドを使う。
本記事のサンプルコードの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.DataFrame
とpandas.Series
の連結の場合、横方向の連結(axis=1
)ではpandas.Series
が新たな列として追加される。pandas.Series
のname
が列名となる。引数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.Series
をpandas.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