在循环中向 pandas 数据帧添加滚动平均值需要很长时间
Posted
技术标签:
【中文标题】在循环中向 pandas 数据帧添加滚动平均值需要很长时间【英文标题】:Adding a rolling average to pandas dataframes in a loop takes forever 【发布时间】:2017-06-06 18:31:20 【问题描述】:我有一个相当大的熊猫数据框字典。键是股票代码,每个数据框有 14 列,包含股票市场数据。例如:
eodscreen['AAPL']
Out[35]:
date open high low close volume ex-dividend \
date
2010-01-04 2010-01-04 5.82 5.980 5.8000 5.98 685500.0 0.0
2010-01-05 2010-01-05 5.99 6.000 5.8300 5.93 419500.0 0.0
...
...
我正在尝试为每只名为“MA”的股票添加一个新列,其中包含“收盘”列的移动平均线。
这是我的简单循环:
for k in eodscreen:
eodscreen[k]['MA'] = eodscreen[k]['close'].rolling(window=5).mean()
这段代码运行大约需要 3 分钟(在几年前的笔记本电脑、i7、16GB RAM 上......)。
我收到以下警告,也许它解释了部分问题?
> A value is trying to be set on a copy of a slice from a DataFrame. Try
> using .loc[row_indexer,col_indexer] = value instead
我不知道什么是“大”字典,所以这可能很正常?
字典:1600 个键,每个键包含一个数据帧。
每个数据框:1 个日期列,13 个 float64 列,每个 1740 行 列。
如果这是意料之中的,您能否提供有关应如何在程序中加载和访问此类数据的见解?它全部存储在一个约 400MB 的 csv 文件中,我在程序开始时将其全部加载并在字典中组织所有内容。最好只读取 1 个股票代码的数据,执行我想要的任何数学运算,重写文件等等,或者我在正确的轨道上认为我可以从内存中完成所有事情(更容易)!
高度赞赏任何 cmets / 见解!
非常感谢!
【问题讨论】:
【参考方案1】:您正在尝试分配恰好是另一个数据帧视图的切片的切片。发生这种情况是因为您最初是如何创建字典的。
解决方法:
for k in eodscreen:
eodscreen[k] = eodscreen[k].assign(MA=df['close'].rolling(window=5).mean())
我建议这应该起作用的原因是您正在将具有新列的数据帧副本重新分配给字典键。
【讨论】:
哇,跑了 5 秒。不过我不太明白你的解释——我的字典不是我想的那样吗? 这就是您的想法。检查其中一个数据框的is_copy
属性。它会以<weak-reference>
之类的奇怪形式返回。这意味着它是另一个数据框的副本,这就是您收到警告的原因。您可能已经从eodscreen[k] = panel[k]
之类的面板中为每个键分配了值,这将分配面板的切片,这是一个数据框,但是因为您使用panel[k]
而不是panel.loc[k]
,所以您得到一个副本而不是一个全新的数据框。泰语是警告试图告诉你的。使用panel.loc[k]
嗯,所以我的字典来自一个日期屏幕,我在“原始”屏幕上做了一个名为“eodall”的词典。 eodscreen = k: eodall[k].ix[startdate:enddate] for k in eodall
所以我的'eodscreen'字典不是新字典,而是指向与eodall相同的数据,只是它的一个子集?
字典是新的,其中的数据框是副本。根据SetWithCopyWarning
这样做而不是eodscreen = k: eodall.loc[k, startdate:enddate] for k in eodall
有趣。您提出的方式意味着数据将在内存中几乎重复。那会是一件坏事吗?以上是关于在循环中向 pandas 数据帧添加滚动平均值需要很长时间的主要内容,如果未能解决你的问题,请参考以下文章
使用Pandas的rolling函数计算滚动平均值(rolling average with Pandas rolling)seaborn使用lineplot函数可视化时间序列数据并添加滚动平均值