【问题标题】:Most efficient way to iterate through list of lists遍历列表列表的最有效方法
【发布时间】:2017-02-03 06:13:10
【问题描述】:

我目前正在从 quandl 收集数据并保存为列表列表。该列表看起来像这样(价格数据):

['2', 1L, datetime.date(1998, 1, 2), datetime.datetime(2016, 9, 26, 1, 35, 3, 830563), datetime.datetime(2016, 9, 26, 1, 35, 3, 830563), '82.1900', '83.6200', '81.7500', '83.5000', '28.5183', 1286500.0]

这通常是大约 5000 个列表中的 1 个,Quandl 每隔一段时间就会吐回一些不喜欢被保存到数据库中的 NaN 值。

['2', 1L, datetime.date(1998, 1, 2), datetime.datetime(2016, 9, 26, 1, 35, 3, 830563), datetime.datetime(2016, 9, 26, 1, 35, 3, 830563), 'nan', 'nan', 'nan', 'nan', 'nan', 0]

遍历列表以将“nan”值更改为零的最有效方法是什么?

我知道我可以做这样的事情,但它似乎相当低效。此操作需要对 11 个不同的值 * 5000 个不同的日期 * 500 家公司执行:

def screen_data(data):
    new_data = []
    for d in data:
        new_list = []
        for x in d:
            new_value = x
            if math.isNan(x):
                new_value = 0
            new_list.append(new_value)

        new_data.append(new_list)
    return new_data

我会对任何可以缩短时间的解决方案感兴趣。我知道 DataFrames 可能会起作用,但不确定它如何解决 NaN 问题。

或者,如果有一种方法可以在 SQLServer5.6 数据库中包含 NaN 值以及浮点数,那么更改数据库也是一个可行的选择。

【问题讨论】:

  • 这在 codereview.stackexchange.com 上可能更好,但你所描述的听起来你必须检查每个列表中的每个值。

标签: python performance list mysql-python nan


【解决方案1】:

不要创建新列表 - 而是就地编辑旧列表:

import math

def screenData(L):
    for subl in L:
        for i,n in enumerate(subl):
            if math.isnan(n): subl[i] = 0

我能想到的唯一方法是使用多处理来加快速度

【讨论】:

    【解决方案2】:

    我还没有计时,但您是否尝试过将 nested list comprehensionconditional expressions 一起使用?

    例如:

    import datetime
    
    data = [
        ['2', 1, datetime.date(1998, 1, 2),
         datetime.datetime(2016, 9, 26, 1, 35, 3, 830563),
         datetime.datetime(2016, 9, 26, 1, 35, 3, 830563),
         '82.1900', '83.6200', '81.7500', '83.5000',
         '28.5183', 1286500.0],
        ['2', 1, datetime.date(1998, 1, 2),
         datetime.datetime(2016, 9, 26, 1, 35, 3, 830563),
         datetime.datetime(2016, 9, 26, 1, 35, 3, 830563),
         'nan', 'nan', 'nan', 'nan', 'nan', 0],
    ]
    
    new_data = [[y if str(y).lower() != 'nan' else 0 for y in x] for x in data]
    
    print(new_data)
    

    我没有使用math.isnan(y),因为您必须确保yfloat number,否则您会收到错误消息。当几乎所有东西都有字符串表示时,这要困难得多。但我仍然确保我对“nan”(使用.lower())进行了小写比较,因为“NaN”或“Nan”是表达“非数字”的合法方式。

    【讨论】:

    • 我也在考虑这个问题,但是您可以通过快速检查是否甚至需要嵌套列表组合来进一步支持它:new_data = [[0 if element == 'nan' else element for element in L] if 'nan' in L else L for L in data] 如果"nan" 被推出单个生成器(而不是手动输入),您可能不需要检查它的变化。
    • 是的,我没想到,但它确实会更快,特别是如果它只是像 OP 所说的那样“每隔一段时间”发生一次。
    【解决方案3】:

    这个怎么样

    import math
    
    def clean_nan(data_list,value=0):
        for i,x in enumerate(data_list):
            if math.isnan(x):
                data_list[i] = value
        return data_list 
    

    (返回是可选的,因为修改是就地进行的,但如果与map 或类似的一起使用,则需要它,当然假设 data_list 是一个列表或类似的容器)

    取决于您获取数据的方式以及使用数据的方式将决定如何使用它,例如,如果您执行类似的操作

    for data in (my database/Quandl/whatever):
        #do stuff with data
    

    你可以改成

    for data in (my database/Quandl/whatever):
        clean_nan(data)
        #do stuff with data
    

    或者使用map或者如果你在python 2中imap

    for data in map(clean_nan,(my database/Quandl/whatever)):
        #do stuff with data
    

    这样您就可以在数据从数据库/Quandl/其他任何地方到达时立即处理您的数据,如果您获取数据的地方也可以用作生成器,那就是不要处理整个事情立即,如果可以,尽可能将其更改为发电机。无论哪种情况,您都可以尽快处理您的数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-07
      • 2021-01-27
      • 1970-01-01
      • 2018-11-01
      • 2021-03-27
      • 2019-09-30
      相关资源
      最近更新 更多