Concat 函数
学习如何使用 concat 函数来合并多个 Pandas DataFrame。
合并 DataFrame
有时我们需要从不同来源收集数据,并将它们合并为一个单一的 DataFrame。具体采用哪种方式取决于数据的特征及其表示形式。
一种常见的方法是将多个 DataFrame 按行上下堆叠,或按列左右拼接。可以将其类比为砌砖墙:砖块既可以横向并排,也可以纵向叠加。Pandas 中的 concat 函数可用于实现这一操作。下面我们通过几个示例来学习该函数的使用方法。假设有如下两个 DataFrame:
我们希望将这两个 DataFrame 上下堆叠合并。以下代码展示了如何完成这一操作:
1import pandas as pd 2 3df1 = pd.DataFrame({"A":[1,5,3,2], "B":[11,6,9,6], "C":["a","d","f","b"]}) 4 5df2 = pd.DataFrame({"A":[2,4,1,7], "B":[14,9,5,8], "C":["b","b","j","a"]}) 6 7df_combined = pd.concat([df1, df2], axis=0) 8 9print(df_combined)
合并后的 DataFrame
| A | B | C | |
|---|---|---|---|
| 0 | 1 | 11 | a |
| 1 | 5 | 6 | d |
| 2 | 3 | 9 | f |
| 3 | 2 | 6 | b |
| 0 | 2 | 14 | b |
| 1 | 4 | 9 | b |
| 2 | 1 | 5 | j |
| 3 | 7 | 8 | a |
原始 DataFrame 的索引被保留了下来。若希望为结果 DataFrame 分配新的连续索引,需将 ignore_index 参数设为 True。需要注意的是,在进行纵向合并时,列名应尽量一致;若存在不匹配的列名,这些列也会出现在结果中,但来自另一 DataFrame 的对应位置会以 NaN 填充。
假设我们现在有以下两个 DataFrame:
我们可以按如下方式合并并重新生成索引:
1import pandas as pd 2 3df1 = pd.DataFrame({"A":[1,5,3,2], "B":[11,6,9,6], "C":["a","d","f","b"]}) 4 5df2 = pd.DataFrame({"A":[2,4,1,7], "B":[14,9,5,8], "D":["b","b","j","a"]}) 6 7df_combined = pd.concat([df1, df2], axis=0, ignore_index=True) 8 9print(df_combined)
合并后的 DataFrame
| A | B | C | D | |
|---|---|---|---|---|
| 0 | 1 | 11 | a | NaN |
| 1 | 5 | 6 | d | NaN |
| 2 | 3 | 9 | f | NaN |
| 3 | 2 | 6 | b | NaN |
| 4 | 2 | 14 | NaN | b |
| 5 | 4 | 9 | NaN | b |
| 6 | 1 | 5 | NaN | j |
| 7 | 7 | 8 | NaN | a |
结果 DataFrame 包含了所有出现过的列名。如果我们只希望保留两个 DataFrame 中都存在的列(即取交集),则需要将 join 参数设置为 "inner"。此时,结果中仅包含列 A 和 B。
如果希望将 DataFrame 左右并列合并(即按列方向拼接),则需将 axis 参数设为 1。在这种情况下,函数不再要求列名一致,而是根据索引是否匹配来进行对齐。我们通过几个例子来说明这种情况。假设有如下两个 DataFrame:
我们可以这样将它们左右拼接:
1import pandas as pd 2 3df1 = pd.DataFrame({"A":[1,5,3,2], "B":[11,6,9,6], "C":["a","d","f","b"]}) 4 5df2 = pd.DataFrame({"A":[2,4,1,7], "B":[14,9,5,8], "D":["b","b","j","a"]}) 6 7df_combined = pd.concat([df1, df2], axis=1) 8 9print(df_combined)
合并后的 DataFrame
| A | B | C | A | B | D | |
|---|---|---|---|---|---|---|
| 0 | 1 | 11 | a | 2 | 14 | b |
| 1 | 5 | 6 | d | 4 | 9 | b |
| 2 | 3 | 9 | f | 1 | 5 | j |
| 3 | 2 | 6 | b | 7 | 8 | a |
由于两个 DataFrame 的索引完全相同,因此结果包含了所有行。接下来尝试另一个例子,使用具有不同索引的 DataFrame。
1import pandas as pd 2 3df1 = pd.DataFrame({"A":[1,5,3,2], "B":[11,6,9,6], "C":["a","d","f","b"]}) 4 5df2 = pd.DataFrame({"A":[2,4,1,7], "B":[14,9,5,8], "D":["b","b","j","a"]}, 6 index=[3,4,5,6]) 7 8df_combined = pd.concat([df1, df2], axis=1) 9 10print(df_combined)
合并后的 DataFrame
| A | B | C | A | B | D | |
|---|---|---|---|---|---|---|
| 0 | 1.0 | 11.0 | a | NaN | NaN | NaN |
| 1 | 5.0 | 6.0 | d | NaN | NaN | NaN |
| 2 | 3.0 | 9.0 | f | NaN | NaN | NaN |
| 3 | 2.0 | 6.0 | b | 2.0 | 14.0 | b |
| 4 | NaN | NaN | NaN | 4.0 | 9.0 | b |
| 5 | NaN | NaN | NaN | 1.0 | 5.0 | j |
| 6 | NaN | NaN | NaN | 7.0 | 8.0 | a |
df1 和 df2 都包含索引 3,其余索引不同。对于无法匹配的索引位置,结果中用 NaN 填充。如果将 join 参数设为 "inner",则结果只会保留索引交集部分,也就是仅保留索引为 3 的那一行。
需要注意的是,concat 函数不仅可以合并两个 DataFrame,还可以同时合并多个。只需将多个 DataFrame 的名称放入列表中,作为 concat 函数的第一个参数即可。上述提到的规则在合并多个 DataFrame 时同样适用。