gpt4 book ai didi

python - 在 pandas 中将函数应用于 DataFrame 中的每个单元格

转载 作者:太空狗 更新时间:2023-10-30 01:26:32 24 4
gpt4 key购买 nike

是否可以就地在 pandas 中将函数应用于 DataFrame 中的每个单元格?

我知道 pandas.DataFrame.applymap但它似乎不允许就地应用:

import numpy as np
import pandas as pd
np.random.seed(1)
frame = pd.DataFrame(np.random.randn(4, 3), columns=list('bde'),
index=['Utah', 'Ohio', 'Texas', 'Oregon'])
print(frame)
format = lambda x: '%.2f' % x
frame = frame.applymap(format)
print(frame)

返回:

               b         d         e
Utah 1.624345 -0.611756 -0.528172
Ohio -1.072969 0.865408 -2.301539
Texas 1.744812 -0.761207 0.319039
Oregon -0.249370 1.462108 -2.060141

b d e
Utah 1.62 -0.61 -0.53
Ohio -1.07 0.87 -2.30
Texas 1.74 -0.76 0.32
Oregon -0.25 1.46 -2.06

frame = frame.applymap(format) 将临时保存 2 个 frame 副本内存,我不想要的。

我知道可以使用 NumPy 数组将函数应用于每个单元格:Mapping a NumPy array in place .

最佳答案

如果我的理解是正确的,pandas 就地操作涉及调用 .update_inplace()方法,例如 .replace()将首先计算新的、替换的数据,然后相应地更新数据框。

.applymap().apply() 的包装器;这些都没有就地选项,但即使有,它们仍然需要在修改数据帧之前将所有输出数据存储在内存中。

来自源头,.applymap()电话 .apply() ,它调用 .aggregate() ,它调用 _aggregate() ,它调用 ._agg() ,这只不过是在 Python (即不是 Cython - 我认为) 中运行的 for 循环。

您当然可以直接修改底层 NumPy 数组:以下代码就地舍入数据框:

frame = pd.DataFrame(np.random.randn(100, 100))

for i in frame.index:
for j in frame.columns:
val = round(frame.values[i,j])
frame.values[i,j] = val

newvals = np.zeros(frame.shape[1])
for i in frame.index:
for j in frame.columns:
val = round(frame.values[i,j])
newvals[j] = val
frame.values[i] = newvals

第一种方式一次设置一个元素,耗时1s左右,第二种方式逐行设置,耗时100ms; .applymap(round)在 20 毫秒内完成。

然而,有趣的是,如果我们使用 frame = pd.DataFrame(np.random.randn(1, 10000)) , 第一种方法和 .applymap(round)大约需要1.2s,第二个大约需要100ms。

最后,frame = pd.DataFrame(np.random.randn(10000,1))第一种和第二种方法采用 1s(不出所料),并且 .applymap(round)需要 10 毫秒。

这些结果或多或少表明.applymap本质上是迭代每一列。

我尝试运行 frame.applymap(round)具有 3 种不同的形状:(10000,1)、(100,100) 和 (1,10000)。第一个最快,第三个最慢;这表明 .applymap()遍历列。以下代码的作用与 .applymap() 大致相同。 , 到位:

newvals = np.zeros(frame.shape[1])
for i in frame.index:
for j in frame.columns:
val = round(frame.values[i,j])
newvals[j] = val
frame.values[i] = newvals

这一个与底层 NumPy 数组的副本一起工作:

newvals = np.zeros(frame.shape[1])
arr = frame.values
for i in frame.index:
for j in frame.columns:
val = round(arr[i,j])
newvals[j] = val
arr[i] = newvals

对于 100x100 数据帧,前者运行大约需要 300 毫秒,而后者需要 60 毫秒——差异完全是因为必须访问 .values。在数据框中!

在 Cython 中运行后者大约需要 34 毫秒,而 .applymap(round)在 24 毫秒内完成。我不知道为什么 .applymap()不过这里仍然更快。

要回答这个问题:可能没有 .applymap() 的就地实现;如果有的话,它很可能会涉及在进行就地更改之前存储所有“应用”值。

如果你想做一个.applymap()就地,您可以迭代底层的 NumPy 数组。然而,这是以性能为代价的——最好的解决方案可能是遍历行或列:例如分配 arr=df.values[i] , 将函数应用于 arr 的每个元素, 通过 df.values[i] = arr 修改数据框,并遍历所有 i .

关于python - 在 pandas 中将函数应用于 DataFrame 中的每个单元格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44939105/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com