python - 在 pandas 中有效地在 250MB 数据帧上移位、连接和除法超过 90 次
问题描述
在尝试转换一个简单的数据集时,我遇到了 pandas 的性能和内存消耗问题。基本上,我试图将分组(按索引)数据集移动 90 次,然后除以移动列的值。
我的基本数据帧在内存中大约有 255MB(大约 11M 行和 5 列),并且使用 parquet 加载并具有多索引。使用我尝试过的方法移动和连接这么多数据,导致荒谬的内存消耗(我假设这是因为 pandas 在进程中管理内存和数据帧副本的方式)。
即使我的机器不受限制,操作本身也需要很长时间,以至于我认为它不切实际。我期望并假设这可以在几分钟内完成。我错了吗?
更具体地说,这是我要执行的操作:
对于数据框中的每一列,创建一个包含 X 天前移位数据的新列
for X in range(1, 90)
,将每列的值除以前一列移位。(所以
columnA.shift(90)
除以columnA.shift(89)
;将所有内容连接到一个数据框中。
我发现纯粹用语言来解释它有点困难,所以这里是一个数据操作的例子:
这是原始数据集(示例只有 2 列):
data = pd.DataFrame(
[[20, 43],
[40, 52],
[30, 34],
[60, 52],
[44, 66],
[55, 72],
[34, 34],
[51, 17]],
columns=['a', 'b'])
换班后:
值除法后:
以下是我尝试过的一些代码片段。
连接循环中的所有移位列(这没有divide
操作)。这实际上是错误的,因为我忘了在groupby()
这里执行:
for w in range(1, 91):
data = pd.concat([
data,
(data[['c1', 'c2', 'c3', 'c4', 'c5']].shift(w).rename(
columns={
'c1': f'c1_{w}',
'c2': f'c2_{w}',
'c3': f'c3_{w}',
'c4': f'c4_{w}',
'c5': f'c5_{w}'
}
))], axis=1)
使用groupby().apply()
:
def _myfunc(x):
for w in range (1, 4):
return (x.shift(w) / x.shift(w - 1)).rename({
'c1': f'c1_{w}',
'c2': f'c2_{w}',
'c3': f'c3_{w}',
'c4': f'c4_{w}',
'c5': f'c5_{w}'
})
data.groupby("mylevel")[['c1', 'c2', 'c3', 'c4', 'c5']].apply(_myfunc)
很高兴在这里获得帮助。
解决方案
这显示了我在评论中提出的问题:
df = pd.DataFrame(np.random.randint(0,100, size=(100, 1)), columns=('a',))
shift_1 = df['a'].shift(1) / df['a']
assert all((df['a'].shift(90) / df['a'].shift(89)).dropna() == shift_1.shift(89).dropna())
dropna() 就在那里,因为np.nan != np.nan
那么,当您可以在查找之前进行转移时,为什么要保留所有副本?
推荐阅读
- java - 考虑在你的配置中定义一个 bean 类型:MyBatis
- stanford-nlp - OPENIE 6 中的连词问题
- javascript - 复选框自动完成未在 Jquery Ajax 中选择先前选中的值
- laravel - 如何在运行时模拟和测试没有迁移模式的模型
- python - 根据文件名中嵌入的时间戳对文件进行排序、分组和处理
- python - 如何将值(时间格式)转换为数字(浮点数)
- node.js - 如何在nodejs项目中动态加载页面内的数据?
- wpf - WPF-如何在单击树视图超链接时重新加载同一页面
- python - keras中的多图像输入
- ios - 初始化而不在swift中传递任何参数?