【发布时间】:2022-01-27 01:11:51
【问题描述】:
假设我们有一个函数bar(df),它返回一个长度为len(df)的numpy数组,给定一个数据帧df。
现在考虑成语
def foo(df):
for i in range(N):
df['FOO_' + str(i)] = bar(df)
return df
最近的熊猫更新开始导致以下警告
PerformanceWarning:DataFrame 高度分散。这通常是 多次调用
frame.insert的结果,差 表现。考虑使用一次连接所有列 pd.concat(axis=1) 代替。要获得碎片整理的帧,请使用newframe = frame.copy()
据我所知,缓解这种情况的一种方法是将上面的代码更改为以下成语
def foo2(df):
frames = [df]
for i in range(N):
frames += [pd.Series(bar(df), index=df.index)]
return pd.concat(frames, axis=1)
上面的代码修复了警告,但导致执行时间更短。
In [110]: %timeit foo()
1.73 s ± 11 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [111]: %timeit foo2()
2.51 s ± 25.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
抑制引入额外开销的性能警告的修复似乎很愚蠢。因此我的问题是
如何在修复警告的同时获得更好的性能。换句话说,有没有办法改进函数 foo2 以提供比 foo 更好的性能?
【问题讨论】:
-
在您的示例中,
N是否等于df的长度?另外,我认为foo不会像您的示例中所写的那样运行:df[i]查找列i,而不是行i。另一个问题是foo覆盖了传入的DataFramedf。 -
@PeterLeimbigler N 是任意的,通常是很大的。我已经编辑了代码以反映您对 df[i] 的评论。至于覆盖,我对此很好,但很好奇:这样做的礼貌方式是什么?
-
@Jernej 你能分享一些数据和
bar()body 吗? -
@DanilaGanchar 有多种情况使用这种成语。我希望看到一个不依赖于特定数据实现或 bar 函数的解决方案。