本文主要介绍pandas中常用的数据合并的方法concat。
先定义一个生产数据的函数:
"""一个简单的DataFrame"""
def make_df(cols, ind):
data = {c: [str(c) + str(i) for i in ind]
for c in cols}
return pd.DataFrame(data, ind)
看下函数效果:
In:
make_df('AB', [1, 2])
Out:
A B
1 A1 B1
2 A2 B2
pd.concat()可以简单地合并一维或多维的 Series 或 DataFrame 对象。
In:
df1 = make_df('AB', [1, 2])
df2 = make_df('AB', [3, 4])
print(df1); print(df2);
print(pd.concat([df1, df2]))
Out:
A B
1 A1 B1
2 A2 B2
A B
3 A3 B3
4 A4 B4
A B
1 A1 B1
2 A2 B2
3 A3 B3
4 A4 B4
默认情况下,DataFrame 的合并都是逐行进行的(默认设置是 axis=0)。pd.concat 也可以通过设置合并坐标轴 axis='col' 或 axis=1 来实现按列合并。例如下面的示例:
In:
df3 = make_df('AB', [0, 1])
df4 = make_df('CD', [0, 1])
print(df3); print(df4);
print(pd.concat([df3, df4], axis=1))
Out:
A B
0 A0 B0
1 A1 B1
C D
0 C0 D0
1 C1 D1
A B C D
0 A0 B0 C0 D0
1 A1 B1 C1 D1
很多时候,将数据合并时,会出现重复索引的问题,如下:
In:
x = make_df('AB', [0, 1])
y = make_df('AB', [2, 3])
y.index = x.index # 复制索引
print(x); print(y);
print(pd.concat([x, y]))
Out:
A B
0 A0 B0
1 A1 B1
A B
0 A2 B2
1 A3 B3
A B
0 A0 B0
1 A1 B1
0 A2 B2
1 A3 B3
针对这个问题,有两种处理方法:
1.忽略索引。有时索引无关紧要,那么合并时就可以忽略它们,可以通过设置 ignore_index 参数来实现。如果将参数设置为 True,那么合并时将会创建一个新的整数索引。
In:
x = make_df('AB', [0, 1])
y = make_df('AB', [2, 3])
y.index = x.index # 复制索引
print(x); print(y); print(pd.concat([x, y],ignore_index=True))
Out:
A B
0 A0 B0
1 A1 B1
A B
0 A2 B2
1 A3 B3
A B
0 A0 B0
1 A1 B1
2 A2 B2
3 A3 B3
(2) 增加多级索引。另一种处理索引重复的方法是通过 keys 参数为数据源设置多级索引标签,这样结果数据就会带上多级索引以便区分,如下:
In:
x = make_df('AB', [0, 1])
y = make_df('AB', [2, 3])
y.index = x.index # 复制索引
print(x); print(y); print(pd.concat([x, y],keys=['x','y']))
Out:
A B
0 A0 B0
1 A1 B1
A B
0 A2 B2
1 A3 B3
A B
x 0 A0 B0
1 A1 B1
y 0 A2 B2
1 A3 B3
使用concat方法合并数据集时有个弊端:如果按默认的逐行合并,那么两个数据集的列名需要一致。如果按列合并数据集,那么两个数据集的行数需要一致。否则就会出现如下NaN的情况。
In:
df1 = make_df('AB', [1, 2])
df2 = make_df('CD', [3, 4])
print(df1); print(df2); print(pd.concat([df1, df2]))
Out:
A B
1 A1 B1
2 A2 B2
C D
3 C3 D3
4 C4 D4
A B C D
1 A1 B1 NaN NaN
2 A2 B2 NaN NaN
3 NaN NaN C3 D3
4 NaN NaN C4 D4
In:
df3 = make_df('AB', [0, 1])
df4 = make_df('CDE', [0, 1,2])
print(df3); print(df4); print(pd.concat([df3, df4], axis=1))
Out:
A B
0 A0 B0
1 A1 B1
C D E
0 C0 D0 E0
1 C1 D1 E1
2 C2 D2 E2
A B C D E
0 A0 B0 C0 D0 E0
1 A1 B1 C1 D1 E1
2 NaN NaN C2 D2 E2
针对这个问题,可以用 join 和 join_ axes 参数设置合并方式。默认的合并方式是对所有输入列进行并集合并( join='outer' ), 当然也可以用 join='inner' 实现对输入列的交集合并:
In:
df5 = make_df('ABC', [1, 2])
df6 = make_df('BCD', [3, 4])
print(df5); print(df6);
print(pd.concat([df5, df6], join='inner'))
Out:
A B C
1 A1 B1 C1
2 A2 B2 C2
B C D
3 B3 C3 D3
4 B4 C4 D4
B C
1 B1 C1
2 B2 C2
3 B3 C3
4 B4 C4
另一种合并方式是直接确定结果使用的列名,设置 join_axes 参数,里面是索引对象构成 的列表(是列表的列表)。如下面示例所示,将结果的列名设置为第一个输入的列名:
In:
df5 = make_df('ABC', [1, 2])
df6 = make_df('BCD', [3, 4])
print(df5); print(df6);
print(pd.concat([df5, df6], join_axes=[df5.columns]))
Out:
A B C
1 A1 B1 C1
2 A2 B2 C2
B C D
3 B3 C3 D3
4 B4 C4 D4
A B C
1 A1 B1 C1
2 A2 B2 C2
3 NaN B3 C3
4 NaN B4 C4
因为直接进行数组合并的需求非常普遍,所以 Series 和 DataFrame 对象都支持 append 方法,让你通过最少的代码实现合并功能。例如,你可以使用 df1.append(df2),效果与 pd.concat([df1, df2]) 一样。
关于concat方法就介绍这么多。
本文摘自《Python数据科学手册》