Pandas:dropna 后就地重命名的性能出现特殊下降
- 2025-03-04 08:24:00
- admin 原创
- 90
问题描述:
我已将此问题报告给pandas 问题。同时,我在此发布此问题,以节省其他人的时间,以防他们遇到类似问题。
在对需要优化的进程进行分析时,我发现非就地重命名列可将性能(执行时间)提高 120 倍。分析表明这与垃圾收集有关(见下文)。
此外,通过避免 dropna 方法恢复了预期的性能。
以下简短示例演示了因子 x12:
import pandas as pd
import numpy as np
就地=真
%%timeit
np.random.seed(0)
r,c = (7,3)
t = np.random.rand(r)
df1 = pd.DataFrame(np.random.rand(r,c), columns=range(c), index=t)
indx = np.random.choice(range(r),r/3, replace=False)
t[indx] = np.random.rand(len(indx))
df2 = pd.DataFrame(np.random.rand(r,c), columns=range(c), index=t)
df = (df1-df2).dropna()
## inplace rename:
df.rename(columns={col:'d{}'.format(col) for col in df.columns}, inplace=True)
100 次循环,3 次最佳:每次循环 15.6 毫秒
第一行输出%%prun
:
ncalls 总时间 每次调用累计时间 每次调用文件名:lineno(函数)
1 0.018 0.018 0.018 0.018 {gc.collect}
就地=假
%%timeit
np.random.seed(0)
r,c = (7,3)
t = np.random.rand(r)
df1 = pd.DataFrame(np.random.rand(r,c), columns=range(c), index=t)
indx = np.random.choice(range(r),r/3, replace=False)
t[indx] = np.random.rand(len(indx))
df2 = pd.DataFrame(np.random.rand(r,c), columns=range(c), index=t)
df = (df1-df2).dropna()
## avoid inplace:
df = df.rename(columns={col:'d{}'.format(col) for col in df.columns})
1000 次循环,3 次中最佳:每次循环 1.24 毫秒
避免 dropna
通过避免使用下列方法来恢复预期的性能dropna
:
%%timeit
np.random.seed(0)
r,c = (7,3)
t = np.random.rand(r)
df1 = pd.DataFrame(np.random.rand(r,c), columns=range(c), index=t)
indx = np.random.choice(range(r),r/3, replace=False)
t[indx] = np.random.rand(len(indx))
df2 = pd.DataFrame(np.random.rand(r,c), columns=range(c), index=t)
#no dropna:
df = (df1-df2)#.dropna()
## inplace rename:
df.rename(columns={col:'d{}'.format(col) for col in df.columns}, inplace=True)
1000 次循环,取 3 次最佳:每次循环 865 µs
%%timeit
np.random.seed(0)
r,c = (7,3)
t = np.random.rand(r)
df1 = pd.DataFrame(np.random.rand(r,c), columns=range(c), index=t)
indx = np.random.choice(range(r),r/3, replace=False)
t[indx] = np.random.rand(len(indx))
df2 = pd.DataFrame(np.random.rand(r,c), columns=range(c), index=t)
## no dropna
df = (df1-df2)#.dropna()
## avoid inplace:
df = df.rename(columns={col:'d{}'.format(col) for col in df.columns})
1000 次循环,3 次中最佳:每次循环 902 µs
解决方案 1:
这是github上解释的一份副本。
无法保证某个inplace
操作实际上会更快。通常它们实际上是对副本执行的相同操作,但顶层引用被重新分配。
本案中业绩出现差异的原因如下。
该(df1-df2).dropna()
调用会创建数据帧的一个切片。当您应用新操作时,这会触发SettingWithCopy
检查,因为它可能是副本(但通常不是)。
此检查必须执行垃圾收集来清除一些缓存引用,以查看它是否是副本。不幸的是,python 语法使这不可避免。
只要先进行复制,就不会发生这种情况。
df = (df1-df2).dropna().copy()
随后的inplace
操作将与以前一样高效。
我的个人观点:我从不使用就地操作。语法更难阅读,而且没有任何优势。
相关推荐
热门文章
项目管理软件有哪些?
热门标签
曾咪二维码
扫码咨询,免费领取项目管理大礼包!
云禅道AD