- 从 Pandas 2.0 版本开始,CoW开始生效但尚未完全实现。
- Pandas 3将强制通过CoW 实现的大多数优化。
COW写时复制
顾名思义,数据修改的时候也会被复制,什么意思呢?
Pandas 支持写时复制,这是一种有助于提高内存使用率的优化技术,尤其是在处理大型数据集时。
- 当 DataFrame 或 Series 共享与原始数据相同的数据时,它最初将为数据共享相同的内存,而不是创建副本。
- 当原始或新 DataFrame 的数据被修改时,将为正在修改的 DataFrame 创建数据的新副本。
这将有效节省内存使用量并提高处理大型数据集时的性能。
在 Pandas 中启用 CoW
它默认未启用,所以我们需要使用copy_on_writePandas 中的配置选项来启用它。
import pandas as pd |
您可以使用任意选项在您的环境中全局启用 CoW。
注意:CoW 将在 Pandas 3.0 中默认启用,因此请尽早习惯它。
CoW 对 Pandas 的影响
CoW 将禁止同时更新多个 pandas 对象。以下是具体操作方式。
import pandas as pd |
使用 CoW,上述代码片段将不会修改df,而只会修改数据subset。
TeX |
就地操作将不起作用
类似地,inplace启用 CoW 后操作将无法进行,CoW 会直接修改原始的df。
Python |
我们可以看到它df保持不变,此外,我们还会看到一个ChainedAssignmentError警告。
上述操作可以用两种不同的方式执行。
- 一种方法是避免 inplace,
- 另一种方法是使用 inplace 在 DataFrame 层直接修改原始 df。
# Avoid inplace |
链式赋值永远不会起作用
当我们在一行代码中使用多个索引操作修改 DataFrame 或 Series 时,这就是我们所说的链式分配技术。
# CoW disabled |
上述代码片段试图更改原来列大于 2 的列。B这df意味着A列中第 2 和第 3 个索引处的值B将被修改。
由于CoW被禁用,因此允许此操作,并且原文df将被修改。
TeX |
但是,如果在 Pandas 中启用了 CoW,那么这将永远无法起作用。
# CoW enabled |
相反,通过写时复制,我们可以用来.loc修改df使用多个索引条件。
# CoW enabled |
这将修改列为1 或大于 3 的列。原始内容B将如下所示。Adf
TeX |
只读数组
当将 Series 或 DataFrame 作为 NumPy 数组访问时,如果该数组与初始 DataFrame 或 Series 共享相同的数据,则该数组将是只读的。
df = pd.DataFrame({"A": [1, 2, 3, 4], "B": ['5', '6', '7', '8']}) |
在上面的代码片段中,arr将是一份副本,因为 df 包含两种不同类型的数组(int和str)。我们可以对 进行修改arr。
arr[1, 0] = 10 |
看一下这个案例:
df = pd.DataFrame({"A": [1, 2, 3, 4], "B": [5, 6, 7, 8]}) |
DataFramedf只有一个 NumPy 数组(相同数据类型的数组),因此arr与 共享数据df。这意味着arr将是只读的,无法就地修改。
print(arr.flags.writeable) |
惰性复制机制
当两个或多个 DataFrame 共享相同的数据时,不会立即创建副本。
df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}) |
由于和共享相同的数据,因此df它们df2在内存中共享相同的引用。仅当任何 DataFrame 被修改时,才会触发复制机制。
df2.iloc[0, 0] = 10 |
但这不是必需的,如果我们不想要 initial df,我们可以简单地将其重新分配给同一个变量(df),这个过程将创建一个新的引用。这将避免写时复制过程。
df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}) |
同样的优化(惰性复制机制)也被添加到不需要复制原始数据的方法中。
DataFrame.rename()
df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}) |
当启用 CoW 时,此方法将返回原始 DataFrame,而不是创建数据的完整副本,这与常规执行不同。
DataFrame.drop() 用于axis=1
DataFrame.drop()类似地,对于for axis=1( axis='columns')也实现了同样的机制。
df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6], "C": [7, 8, 9]}) |
结论
Pandas 3.0 版将默认实现写时复制 (CoW)。
所有这些符合 CoW 的优化将在处理大型数据集时实现高效的内存和资源管理。
这将减少不可预测或不一致的行为并大大提高性能。