查找列表中邻居的最有效方法

时间:2015-12-14 12:19:41

标签: python list python-2.7

我有一个2016年的长度列表,但只有242包含数据,其余的设置为无。我的目标是在值之间插值以用IDW(反距离加权)的简单形式填充所有间隙。 所以我的脚本的任务是:

  • 迭代myList的所有项目
  • 如果myList包含一个值(即无),只需将其复制
  • 如果你发现"无"在myList中,通过计算myList
  • 中所有项目的距离来获取左右邻居的位置/值
  • 计算两个邻居间隙的插值(他们离开的距离越远,他们得到的重量就越少)

假设我们只有14个项目(5个有效项目)的较小列表:

distance = [i - j for j in range(len(myList)) if not myList[j] is None]

我正在为许多数据集做这件事。我发现这种方法每个数据集大约需要0.59秒。困扰我的是我的列表全部排序,但我只需要2个值。所以99%的距离都是无差别计算的。这导致我尝试两个:在i-j变为负数后停止迭代,因为那时显然它遇到了最接近的值:

所以不是列表理解:

dist = []
for j in range(len(myList)):
    if not myList[j] is None:
        dist.append(i-j)
        if i-j < 0: break

我做了一个正确的for循环,我在距离为零后退出并因此再次变大:

{{1}}

使用这种方法,我可以将每个数据集降低到0.38秒。迭代myList中的所有项目时,第二种方法在开始时很快(项目在第2,第3,第4,......循环之后被点击并立即退出),但最后项目没有任何改进,因为迭代始终开始在j = 0。

我想知道你是否能想出更快的方法来找到数据集中特定数字的两个邻居,而不必检查所有距离,只取最大负数和小正数。

另外,我对python很新,所以如果你在我的脚本中找到其他非pythonic表达式,请告诉我。非常感谢你们!

1 个答案:

答案 0 :(得分:2)

<强>更新 以下是使用numpy interp

的方法
import numpy as np

myList = [26, None, None, None, 31, None, None, 58, None, 42, None, None, None, 79]

values = [(i, val) for i, val in enumerate(myList) if val is not None]

xp, fp = zip(*values)

print(xp) # (0, 4, 7, 9, 13)
print(fp) # (26, 31, 58, 42, 79)

result = np.interp(np.arange(len(myList)), xp, fp)
print(result) # [ 26.    27.25  28.5   29.75  31.    40.    49.    58.    50.    42.    51.25  60.5   69.75  79.  ]

原帖:

正如其他人已经建议的那样,你最好使用已经在numpy或pandas中实现的插值。

然而,为了完整起见,我提出了一个快速解决方案:

myList = [26, None, None, None, 31, None, None, 58, None, 42, None, None, None, 79]

resultList = []

# first lets split the list into sublists that group the numbers
# and the Nones into groups
for i, item in enumerate(myList):
    if i == 0:
        resultList.append([item])
    else:
        if type(resultList[-1][-1]) == type(item):
            resultList[-1].append(item)
        else:
            resultList.append([item])

print(resultList) # [[26], [None, None, None], [31], [None, None], [58], [None], [42], [None, None, None], [79]]

# now lets interpolate the sublists that contain Nones
for i, item in enumerate(resultList):
    if item[0] is not None:
        continue

    # this is a bit problematic, what do we do if we have a None at the beginning or at the end?
    if i == 0 or i + 1 == len(resultList):
        continue

    prev_item = resultList[i - 1][-1]
    next_item = resultList[i + 1][0]

    difference = next_item - prev_item
    item_length = len(item) + 1

    for j, none_item in enumerate(item):
        item[j] = prev_item + float(j + 1) / item_length * difference

# flatten the list back
resultList = [item for sublist in resultList for item in sublist]

print(resultList) # [26, 27.25, 28.5, 29.75, 31, 40.0, 49.0, 58, 50.0, 42, 51.25, 60.5, 69.75, 79]

我建议您仅将此用于学习或简单案例,因为它不会处理您的列表以None开头或结尾的情况