大数据集崩溃 python 脚本

Large data set crashes python script

我有一个使用 GyPython 组件的简单脚本 Rhino/Grasshopper。目标是将每小时的天气数据(只记录了一些小时)分配给小时。如果没有测量它 returns 0。它应该像这样工作(具有相似值的示例):

hoursList = [hr1,hr2,hr3,hr4,hr5,hr6]
measuredList = [hr2,hr3,hr6]
recordList = [wData1,wData2,wData3]
finalList = []    

def assignData(i,y):        
    for i < len(leadList):            
        if hoursList[i] == measuredList[y]:                
            finalList.append(recordList[y])                
            i += 1
            y += 1                
        else:                
            finalList.append(0)                
            i += 1    
        assignData(i,y)    

i = 0
y = 0    
assignData(i,y)

应该return

[0,wData1,wData2,0,0,wData3]

本案例的结果 finalList(添加换行符以提高可读性)

[0, 'wData1', 'wData2', 0, 0, 'wData3', 'wData3',
 0, 'wData3', 'wData3', 0, 0, 'wData3', 'wData3',
 0, 'wData3', 'wData3', 'wData2', 0, 0, 'wData3', 'wData3',
 0, 'wData3', 'wData3', 0, 0, 'wData3', 'wData3',
 0, 'wData3', 'wData3', 'wData1', 'wData2', 0, 0, 'wData3', 'wData3',
 0, 'wData3', 'wData3', 0, 0, 'wData3', 'wData3',
 0, 'wData3', 'wData3', 'wData2', 0, 0, 'wData3', 'wData3',
 0, 'wData3', 'wData3', 0, 0, 'wData3', 'wData3',
 0, 'wData3', 'wData3']

当我尝试在大型数据列表(大约 43000 个值)上 运行 这段代码时,它在大约 7000 次迭代后崩溃。我检查了 sys.getrecursionlimit,它是 2147483647。有什么想法可以让这项工作成功吗?

分析

我猜len(leadList)就是你给的43000这个数字。我称之为 limit.

注意你的循环是如何工作的:对于 "input i" 到 limit 范围内的每个 i 值,这处理一个项目,递增 i(也许y), 并重复出现。因此,您在 i=0 的顶级调用将产生对 assignData(1, 0) 的调用(假设失败)并等待它完成。然后它将回到循环的顶部,使用 i=1,并继续...最终连续产生 limit 个递归调用。

初始调用现在将在范围 (1, limit) 内工作,生成 limit-1 调用,第一个调用将生成 limit-2 调用,等等。每个级别都会产生另一个具有大扇出的级别。

简而言之,您发出的呼叫比我认为您意识到的要多得多;当你增加 limit.

时,总数增长得相当快

我怀疑您的问题是 finalList 超出了可用内存,因为这些调用中的每一个都附加了一个元素。

调查

将基本调试语句插入您的代码中:

def assignData(i, y):
    print "ENTER", i, y, finalList
    for i < len(leadList):
        ...

这样您就可以看到通话进度。

修复

我怀疑您是否需要这个双重嵌套的递归堆栈。事实上,我不认为递归能给你带来任何好处。看起来您只需要遍历列表一次,找到实际对应的时间,否则填入 0。去掉调用,适当使用for来控制i的值,适当减少代码。

def assignData():
    y = 0        
    for i in range(0, len(leadList)):            
        if hoursList[i] == measuredList[y]:                
            finalList.append(recordList[y])                
            y += 1                
        else:                
            finalList.append(0)

更好的解决方案

如果你只需要匹配时间的记录,你可以更直接。建立一个字典来索引时代的测量。

meas = dict(zip(measuredList, recordList)

现在,编写一个列表推导式以在不在字典中的任何时间插入 0。

finalList = [meas[time] if time in meas else 0
                for time in hourslist]

如果我正确地解读了你的问题,那就是你的总体目标。