如何制作for循环,迭代超过15mln记录,节省空间?

时间:2017-03-20 07:30:42

标签: python python-3.x for-loop space-complexity

我遇到一个简单的for循环问题。我正在尝试从列表中计算最大值(即移位窗口列表),创建这些最大值的列表,我稍后将其添加到数据框中。

我的数据框有两列浮点值和日期时间索引。数据文件有大约1500万行(即我要迭代的系列的长度是15mln)(700 MB)。

当我在一段时间后运行我的简单循环时,我的计算机内存耗尽并崩溃。我有12 GB的RAM。

我的代码:

import pandas as pd
import numpy as np

# sample data
speed = np.random.uniform(0,25,15000000)

data_dict = {'speed': speed}
df = pd.DataFrame(data_dict)

# create a list of 'windows', i.e. subseries of the list 
def GetShiftingWindows(thelist, size):
    return [ thelist[x:x+size] for x in range( len(thelist) - size + 1 ) ]

window_size = 10

list_of_win_speeds = GetShiftingWindows(df.speed, window_size)

list_of_max_speeds = []

for x in list_of_win_speeds: 
    max_value = max(x)
    list_of_max_speeds.append(max_value)

我不是CS专业。在我看来,这似乎是一个空间复杂性问题。我在这里错过了什么才能使计算成为可能?

2 个答案:

答案 0 :(得分:3)

作为第一步,我会改变

return [ thelist[x:x+size] for x in range( len(thelist) - size + 1 ) ]

return ( thelist[x:x+size] for x in range( len(thelist) - size + 1 ) )

然后你将得到一个生成器,你的代码在内存中创建整个子列表列表,生成器方法每个for迭代只生成一个子列表

如果您使用Python 2,您还可以将range(一次生成整个列表)更改为xrange(再次生成每个调用只生成一个值)

最后,您可以使用islice返回迭代器生成器:

from itertools import islice

return ( islice(thelist, x, x + size) for x in range( len(thelist) - size + 1 ) )

答案 1 :(得分:1)

首先,您应该使用pandas聚合函数,而不是尝试迭代列表并自行完成。目前尚不清楚这个函数到底应该做什么:

def GetShiftingWindows(thelist, size):
    return [ thelist[x:x+size] for x in range( len(thelist) - size + 1 ) ]

但它做的是创建一个非常大的字典。考虑投资yield。当您使用yield时,您不会将这个大字典存储在内存中。

def GetShiftingWindows(thelist, size):
    for x in range( len(thelist) - size + 1 ):
        yield thelist[x:x+size]

您可以使用xrange() instead of range()来挤出另外几个字节。

yield和xrange的优点是它不会在内存中存储列表。而是生成一个具有较小内存要求的延迟评估迭代。