python数字合并提高,Python 数据处理(三十一)—— 合并连接之 concat

前言

pandas 提供了各种工具,可以轻松地将不同的 Series 或 DataFrame 连接、合并在一起

此外,pandas 还提供了比较两个 Series 或 DataFrame 对象差异的实用工具

连接对象

concat() 函数能够沿指定轴执行连接操作,同时对其他轴上的索引(如果有的话,Series 只有一个轴)执行可选的集合运算(并集或交集)

下面是一个简单的示例

In [1]: df1 = pd.DataFrame(

...: {

...: "A": ["A0", "A1", "A2", "A3"],

...: "B": ["B0", "B1", "B2", "B3"],

...: "C": ["C0", "C1", "C2", "C3"],

...: "D": ["D0", "D1", "D2", "D3"],

...: },

...: index=[0, 1, 2, 3],

...: )

...:

In [2]: df2 = pd.DataFrame(

...: {

...: "A": ["A4", "A5", "A6", "A7"],

...: "B": ["B4", "B5", "B6", "B7"],

...: "C": ["C4", "C5", "C6", "C7"],

...: "D": ["D4", "D5", "D6", "D7"],

...: },

...: index=[4, 5, 6, 7],

...: )

...:

In [3]: df3 = pd.DataFrame(

...: {

...: "A": ["A8", "A9", "A10", "A11"],

...: "B": ["B8", "B9", "B10", "B11"],

...: "C": ["C8", "C9", "C10", "C11"],

...: "D": ["D8", "D9", "D10", "D11"],

...: },

...: index=[8, 9, 10, 11],

...: )

...:

In [4]: frames = [df1, df2, df3]

In [5]: result = pd.concat(frames)

就像 ndarrays 上的函数 numpy.concatenate 一样,pandas.concat 接收一个相同类型的对象列表或字典,并通过一些配置来设置处理方式并将它们连接起来

pd.concat(

objs,

axis=0,

join="outer",

ignore_index=False,

keys=None,

levels=None,

names=None,

verify_integrity=False,

copy=True,

)

让我们再来看看上面的例子。假设我们想将特定的键与被切割的 DataFrame 的每一个片段关联起来。我们可以使用 keys 参数来实现。

In [6]: result = pd.concat(frames, keys=["x", "y", "z"])

从图中可以看出,在结果对象的索引的最外层添加了相应的索引(变为层次索引)。这意味着我们现在可以按键选择每个块

In [7]: result.loc["y"]

Out[7]:

A B C D

4 A4 B4 C4 D4

5 A5 B5 C5 D5

6 A6 B6 C6 D6

7 A7 B7 C7 D7

下面将详细介绍此功能

注意:

concat()、append() 都会对数据进行完整的复制,不断重复使用这个函数会造成显著的性能下降。

如果你想在多个数据集上执行该操作,可以使用列表推导式。

frames = [ process_your_file(f) for f in files ]

result = pd.concat(frames)

同时,当在指定轴上连接 DataFrames 时,pandas 将尽可能尝试保留这些索引或列名。

1 在其他轴上的设置逻辑

当将多个 DataFrame 连接在一起时,您可以通过以下两种方式来选择如何处理其他轴上的数据(即除被连接的轴外)。

并集 join='outer',这是默认选项,因为它不会丢失信息

交集 join='inner'

下面是这些方法的一个示例。首先,对于默认的 join='outer'

In [8]: df4 = pd.DataFrame(

...: {

...: "B": ["B2", "B3", "B6", "B7"],

...: "D": ["D2", "D3", "D6", "D7"],

...: "F": ["F2", "F3", "F6", "F7"],

...: },

...: index=[2, 3, 6, 7],

...: )

...:

In [9]: result = pd.concat([df1, df4], axis=1)

对于 join='inner' 也是一样的

In [10]: result = pd.concat([df1, df4], axis=1, join="inner")

最后,假设我们只是想重用原始 DataFrame 中的确切索引

In [11]: result = pd.concat([df1, df4], axis=1).reindex(df1.index)

类似地,我们可以在连接之前进行索引

In [12]: pd.concat([df1, df4.reindex(df1.index)], axis=1)

Out[12]:

A B C D B D F

0 A0 B0 C0 D0 NaN NaN NaN

1 A1 B1 C1 D1 NaN NaN NaN

2 A2 B2 C2 D2 B2 D2 F2

3 A3 B3 C3 D3 B3 D3 F3

2 使用 append 连接

Series 和 DataFrame 上的 append() 实例方法是 concat() 的一个简单的快捷方式。

该方法实际上早于 concat。它沿着 axis=0 即索引方向进行连接

In [13]: result = df1.append(df2)

在 DataFrame 中,索引必须是不相交的,但列不需要

In [14]: result = df1.append(df4, sort=False)

append 可以接受多个对象来进行连接

In [15]: result = df1.append([df2, df3])

注意:

这里的 append() 方法不同于 list,该方法不会修改 df1 的值,同时返回是添加 df2 后的拷贝

3 忽略连接轴上的索引

对于某些 DataFrame 对象,其上的索引并没有任何意义,同时你可能希望在连接的时候,忽略这些对象的索引可能存在重叠的情况。

要做到这一点,可以使用 ignore_index 参数

In [16]: result = pd.concat([df1, df4], ignore_index=True, sort=False)

这也是 DataFrame.append() 的一个有效参数

In [17]: result = df1.append(df4, ignore_index=True, sort=False)

4 不同维度数据的连接

您也可以将 Series 和 DataFrame 对象连接起来。Series 将被转换为 DataFrame,列名为 Series 的名称

In [18]: s1 = pd.Series(["X0", "X1", "X2", "X3"], name="X")

In [19]: result = pd.concat([df1, s1], axis=1)

对于未命名的 Series,对应的列名将是连续增长的数字

In [20]: s2 = pd.Series(["_0", "_1", "_2", "_3"])

In [21]: result = pd.concat([df1, s2, s2, s2], axis=1)

传递 ignore_index=True 将删除所有名称引用

In [22]: result = pd.concat([df1, s1], axis=1, ignore_index=True)

5 使用 keys 连接

keys 参数的一个常见的用法是,基于现有 Series 创建新 DataFrame 时覆盖列名

默认的行为是如果 Series 的名称存在的话,让生成的 DataFrame 继承

In [23]: s3 = pd.Series([0, 1, 2, 3], name="foo")

In [24]: s4 = pd.Series([0, 1, 2, 3])

In [25]: s5 = pd.Series([0, 1, 4, 5])

In [26]: pd.concat([s3, s4, s5], axis=1)

Out[26]:

foo 0 1

0 0 0 0

1 1 1 1

2 2 2 4

3 3 3 5

通过 keys 参数,我们可以覆盖现有的列名

In [27]: pd.concat([s3, s4, s5], axis=1, keys=["red", "blue", "yellow"])

Out[27]:

red blue yellow

0 0 0 0

1 1 1 1

2 2 2 4

3 3 3 5

让我们考虑第一个例子的一个变体

In [28]: result = pd.concat(frames, keys=["x", "y", "z"])

你也可以在 concat 中传递一个字典,在这种情况下,字典的键将用于 keys 参数(除非指定了其他键)

In [29]: pieces = {"x": df1, "y": df2, "z": df3}

In [30]: result = pd.concat(pieces)

In [31]: result = pd.concat(pieces, keys=["z", "y"])

结果中创建了 MultiIndex,最外层为 keys 参数指定的值,而原 DataFrame 的索引在内层保留了下来

In [32]: result.index.levels

Out[32]: FrozenList([['z', 'y'], [4, 5, 6, 7, 8, 9, 10, 11]])

如果你想指定其他级别,可以使用 levels 参数:

In [33]: result = pd.concat(

....: pieces, keys=["x", "y", "z"], levels=[["z", "y", "x", "w"]], names=["group_key"]

....: )

....:

In [34]: result.index.levels

Out[34]: FrozenList([['z', 'y', 'x', 'w'], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]])

6 将行追加到DataFrame

虽然这样做效率很低,但是你可以通过传递一个 Series 或 dict 并将其追加到 DataFrame 中,同时会返回一个新的 DataFrame

In [35]: s2 = pd.Series(["X0", "X1", "X2", "X3"], index=["A", "B", "C", "D"])

In [36]: result = df1.append(s2, ignore_index=True)

你应该使用 ignore_index 来指示 DataFrame 丢弃它的索引。

如果你希望保留索引,你应该为 DataFrame 构造一个合适的索引,然后追加或连接这些对象

你也可以传递字典或 Series 列表:

In [37]: dicts = [{"A": 1, "B": 2, "C": 3, "X": 4}, {"A": 5, "B": 6, "C": 7, "Y": 8}]

In [38]: result = df1.append(dicts, ignore_index=True, sort=False)

你可能感兴趣的:(python数字合并提高)