2017-08-30 108 views
4

我有两个不同长度的Python列表。人们可能会认为其中一个列表比另一个列表大数倍。两个Python列表的匹配长度

这两个列表都包含相同的物理数据,但采集的采样率不同。

我的目标是对较大的信号进行降采样,使其具有与较小信号一样多的数据点。

我想出了下面的代码,基本上没有工作,但既不是非常Python化,也不能够在一个高性能的方式处理非常大的列表:

import math 

a = [1,2,3,4,5,6,7,8,9,10] 
b = [1,4.5,6.9] 

if len(a) > len(b): 
    div = int(math.floor(len(a)/len(b))) 
    a = a[::div] 
    diff = len(a)-len(b) 
    a = a[:-diff] 
else: 
    div = int(math.floor(len(b)/len(a))) 
    b = b[::div] 
    diff = len(b)-len(a) 
    b = b[:-diff] 
print a 
print b 

如果有经验的Python用户可以详细说明我会赞赏替代方法来解决这个任务。

任何答复或评论是高度赞赏。

+0

请注意,通过提高分部的底部,对于较长的列表可能会有一个大的累积误差!例如。,如果一个列表包含7个元素,另一个列表包含4个元素,那么您将只取前四个元素,而不是每个元素。 –

+0

@tobias_k的确如此。然而在我的例子中,一个列表可能有80000个元素,另一个列表可能只有300个。 – Rickson

回答

1

下面的代码的缩写版本(不一定是更好的性能):

a = [1,2,3,4,5,6,7,8,9,10] 
b = [1,4.5,6.9] 
order = 0 # To determine a and b. 

if len(b) > len(a): 
    a, b = b, a # swap the values so that 'a' is always larger. 
    order = 1 

div = len(a)/len(b) # In Python2, this already gives the floor. 
a = a[::div][:len(b)] 

if order: 
    print b 
    print a 
else: 
    print a 
    print b 

既然你最终放弃一些较大的列表后期元素,明确for循环可以提高性能,如那么你不必“跳”到将被丢弃的值:

new_a = [] 
jump = len(b) 
index = 0 
for i in range(jump): 
    new_a.append(a[index]) 
    index += jump 
a = new_a 
+1

您可以进一步简化为'a = a [:: div] [:len(b)]''。如果我们从头开始计算,则不需要新的“a”长度。也更清楚什么是意图恕我直言。 –

+0

@tobias_k谢谢!我已经添加了它。你对我的其他代码有什么看法? –

+0

但是,请注意,OP的原始代码不会交换变量......进一步下线的代码可能需要进行调整,否则您应该再次交换。 –

0

如果你遍历列表,你可以使用一个发电机,因此您不必复制整个事情记忆。

from __future__ import division 

a = [1,2,3,4,5,6,7,8,9,10] 
b = [1,4.5,6.9] 

def zip_downsample(a, b): 
    if len(a) > len(b): 
     b, a = a, b # make b the longer list 
    for i in xrange(len(a)): 
     yield a[i], b[i * len(b) // len(a)] 

for z in zip_downsample(a, b): 
    print z 
-1
#a = [1,2,3,4,5,6,7,8,9,10] 
#b = [1,4.5,6.9] 

a, b = zip(*zip(a, b)) 

# a = [1, 2, 3] 
# b = [1, 4.5, 6.9] 

内拉链结合列表到收杆,丢弃从大名单中多余的物品,返回类似[(1, 1), (2, 4.5), (3, 6.9)]。然后外部zip执行与此相反的操作(因为我们用*操作符解压缩),但由于我们已经用第一个zip压缩了多余部分,所以列表应该是相同的大小。这返回为[a, b],所以我们然后解压到相应的变量(a, b = ...)。

https://www.programiz.com/python-programming/methods/built-in/zip对拉链的详细信息,并使用它,因为它是自己的反面

+1

a的预期输出是'[1,4,7]',b不需要计算 – dansalmo

1

首先,要对性能,你应该使用numpy。该问题被标记为numpy,所以也许你已经是,并没有表现出来,但在任何情况下,列表可以被转换成具有

import numpy as np 
a = np.array(a) 
b = np.array(b) 

索引到numpy的数组是一样的。 可以在阵列上使用len,但array.shape更通用,给出以下(非常相似)的代码。

a[::a.shape[0] // b.shape[0]] 

表现明智,这应该会大大提高大多数数据的速度。 使用更大的a和b阵列(分别为10e6和1e6元素)进行测试,表明numpy可以大大提高性能。

a = np.ones(10000000) 
b = np.ones(1000000) 

%timeit a[::a.shape[0] // b.shape[0]] # Numpy arrays 
1000000 loops, best of 3: 348 ns per loop 

a = list(a); 
b = list(b); 
%timeit a[::len(a) // len(b)] # Plain old python lists 
1000000 loops, best of 3: 29.5 ms per loop