我有一个2016年的长度列表,但只有242包含数据,其余的设置为无。我的目标是在值之间插值以用IDW(反距离加权)的简单形式填充所有间隙。 所以我的脚本的任务是:
假设我们只有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表达式,请告诉我。非常感谢你们!
答案 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
开头或结尾的情况