# 3.2.3:Concat与Append操作 ## 相关知识 在`Numpy`中,我们介绍过可以用`np.concatenate`、`np.stack`、`np.vstack`和`np.hstack`实现合并功能。`Pandas`中有一个`pd.concat()`函数与`concatenate`语法类似,但是配置参数更多,功能也更强大,主要参数如下。 参数名|说明 :-:|:-: objs|参与连接的对象,必要参数 axis|指定轴,默认为0 join|inner或者outer,默认为outer,指明其他轴的索引按哪种方式进行合并,inner表示取交集,outer表示取并集 join_axes|指明用于其他n-1条轴的索引,不执行并集/交集运算 keys|与连接对象有关的值,用于形成连接轴向上的层次化索引。可以是任意值的列表或数组 levels|指定用作层次化索引各级别上的索引 names|用于创建分层级别的名称,如果设置了keys和levels verify_integrity|检查结果对象新轴上的重复情况,如果发现则引发异常。默认False允许重复 ignore_index|不保留连接轴上的索引,产生一组新索引 --- `pd.concat()`可以简单地合并一维的`Series`或`DataFrame`对象。 ```python # Series合并 ser1 = pd.Series(['A', 'B', 'C'], index=[1, 2, 3]) ser2 = pd.Series(['D', 'E', 'F'], index=[4, 5, 6]) pd.concat([ser1,ser2]) Out: 1 A 2 B 3 C 4 D 5 E 6 F dtype: object # DataFrame合并,将concat的axis参数设置为1即可横向合并 df1 = pd.DataFrame([["A1","B1"],["A2","B2"]],index=[1,2],columns=["A","B"]) df2 = pd.DataFrame([["A3","B3"],["A4","B4"]],index=[3,4],columns=["A","B"]) pd.concat([df1,df2]) Out: A B 1 A1 B1 2 A2 B2 3 A3 B3 4 A4 B4 ``` ## 合并时索引的处理 `np.concatenate`与`pd.concat`最主要的差异之一就是`Pandas`在合并时会保留索引,即使索引是重复的! ```python df3 = pd.DataFrame([["A1","B1"],["A2","B2"]],index=[1,2],columns=["A","B"]) df4 = pd.DataFrame([["A3","B3"],["A4","B4"]],index=[1,2],columns=["A","B"]) pd.concat([df3,df4]) Out: A B 1 A1 B1 2 A2 B2 1 A3 B3 2 A4 B4 ``` 1. 如果你想要检测`pd.concat()`合并的结果中是否出现了重复的索引,可以设置`verify_integrity`参数。将参数设置为`True`,合并时若有索引重复就会触发异常。 ``` try: pd.concat([df3, df4], verify_integrity=True) except ValueError as e: print("ValueError:", e) Out: ValueError: Indexes have overlapping values: [0, 1] ``` 2. 有时索引无关紧要,那么合并时就可以忽略它们,可以通过设置 `ignore_index`参数为`True`来实现。 ```python pd.concat([df3,df4],ignore_index=True) Out: A B 0 A0 B0 1 A1 B1 2 A2 B2 3 A3 B3 ``` 3. 另一种处理索引重复的方法是通过`keys`参数为数据源设置多级索引标签,这样结果数据就会带上多级索引。 ```python pd.concat([df3, df4], keys=['x', 'y']) Out: A B x 0 A0 B0 1 A1 B1 y 0 A2 B2 1 A3 B3 ``` ## join和join_axes参数 前面介绍的简单示例都有一个共同特点,那就是合并的`DataFrame`都是同样的列名。而在实际工作中,需要合并的数据往往带有不同的列名,而 `pd.concat`提供了一些参数来解决这类合并问题。 ```python df5 = pd.DataFrame([["A1","B1","C1"],["A2","B2","C2"]],index=[1,2],columns=["A","B","C"]) df6 = pd.DataFrame([["B3","C3","D3"],["B4","C4","D4"]],index=[3,4],columns=["B","C","D"]) pd.concat([df5,df6]) Out: A B C D 1 A1 B1 C1 NaN 2 A2 B2 C2 NaN 3 NaN B3 C3 D3 4 NaN B4 C4 D4 ``` 可以看到,结果中出现了缺失值,如果不想出现缺失值,可以使用`join`和`join_axes`参数。 ```python pd.concat([df5,df6],join="inner") # 合并取交集 Out: B C 1 B1 C1 2 B2 C2 3 B3 C3 4 B4 C4 # join_axes的参数需为一个列表索引对象 pd.concat([df5,df6],join_axes=[pd.Index(["B","C"])]) Out: B C 1 B1 C1 2 B2 C2 3 B3 C3 4 B4 C4 ``` ## append()方法 因为直接进行数组合并的需求非常普遍,所以`Series`和`DataFrame` 对象都支持`append`方法,让你通过最少的代码实现合并功能。例如,`df1.append(df2)`效果与`pd.concat([df1,df2])`一样。但是它和`Python`中的`append`不一样,**每次使用`Pandas`中的`append()`都需要重新创建索引和数据缓存**。