Python中的嵌套列表理解

时间:2015-04-17 22:02:20

标签: python numpy list-comprehension slice

我有一个列表理解我正试图让我的头脑,我似乎无法得到我想要的东西,并认为我会看到其他人是否知道如何!

我的基本数据结构如下:

structure = [[np.array([[1,2,3],[4,5,6]]), np.array([[7,8,9],[10,11,12]])], [np.array([[13,14,15],[16,17,18]]), np.array([[19,20,21],[22,23,24]])]]

所以我有一个包含numpy数组子列表的整体列表,我想要的输出是某种分组(不管它是列表还是数组),并且配对了以下元素:

[1, 13]
[4, 16]
[2, 14]
[5, 17]
[3, 15]
[6, 18]

我以为我会使用以下样式构造:

output = [structure[i][0][j] for j in range(9) for i in range(len(structure))]但是,唉,没有快乐。

我真的不介意它是否需要不止一个阶段 - 只是想将这些元素组合在一起!

(作为一些背景知识 - 我已经获得了从各种模型输出的概率列表,在这些模型中我有一个训练列表和一个验证列表:

[[model_1], [model_2], ..., [model_n]]

其中[model_1][[training_set], [validation_set], [test_set]]

[training_set]np.array([p_1, p_2, ..., p_n],[p_1, p_2, ..., p_n],...])

我想将每个模型的项目1的预测组合在一起,并创建一个长度等于我得到的模型数量的训练向量。然后,我想对[training_set]的第二行做同样的事情。

如果这没有意义,请告诉我!

4 个答案:

答案 0 :(得分:3)

由于structure中的所有数组(和子列表)大小相同,您可以将其转换为一个更高维的数组:

In [189]: A=np.array(structure)
Out[189]: 
array([[[[ 1,  2,  3],
         [ 4,  5,  6]],

        [[ 7,  8,  9],
         [10, 11, 12]]],


       [[[13, 14, 15],
         [16, 17, 18]],

        [[19, 20, 21],
         [22, 23, 24]]]])

In [190]: A.shape
Out[190]: (2, 2, 2, 3)

重塑和交换方式可以为您提供各种组合。

例如,可以使用以下选项选择样本子列表中的值:

In [194]: A[:,0,:,:]
Out[194]: 
array([[[ 1,  2,  3],
        [ 4,  5,  6]],

       [[13, 14, 15],
        [16, 17, 18]]])

并重新塑造

In [197]: A[:,0,:,:].reshape(2,6)
Out[197]: 
array([[ 1,  2,  3,  4,  5,  6],
       [13, 14, 15, 16, 17, 18]])

并转置以获得6对对:

In [198]: A[:,0,:,:].reshape(2,6).T
Out[198]: 
array([[ 1, 13],
       [ 2, 14],
       [ 3, 15],
       [ 4, 16],
       [ 5, 17],
       [ 6, 18]])

要按照1,4,2,5..顺序获取它们,我可以先转置

In [208]: A[:,0,:,:].T.reshape(6,2)
Out[208]: 
array([[ 1, 13],
       [ 4, 16],
       [ 2, 14],
       [ 5, 17],
       [ 3, 15],
       [ 6, 18]])

答案 1 :(得分:2)

不确定您想要的完整输出,但这可能会有所帮助:

imort numpy as np

structure = [[np.array([[1, 2, 3], [4, 5, 6]]), np.array([[7, 8, 9], [10, 11, 12]])],
             [np.array([[13, 14, 15], [16, 17, 18]]), np.array([[19, 20, 21], [22, 23, 24]])]]

from itertools import chain

zipped = (zip(*ele) for ele in zip(*next(zip(*structure))))

print (list(chain.from_iterable(zip(*zipped))))
[(1, 13), (4, 16), (2, 14), (5, 17), (3, 15), (6, 18)]

好了巫术的细分:

# transpose sub arrays so column 0 is the first two sub elements from 
# each sub array
In [4]: start = zip(*structure)

In [5]: start
Out[5]: 
[(array([[1, 2, 3],
         [4, 5, 6]]), array([[13, 14, 15],
         [16, 17, 18]])), (array([[ 7,  8,  9],
         [10, 11, 12]]), array([[19, 20, 21],
         [22, 23, 24]]))]

# our interesting sub array's i.e colunm[0]
In [6]: first_col = next(start)

In [7]: first_col
Out[7]: 
(array([[1, 2, 3],
        [4, 5, 6]]), array([[13, 14, 15],
        [16, 17, 18]]))

# pair up corresponding sub array's
In [8]: intersting_pairs = zip(*first_col)

In [9]: intersting_pairs
Out[9]: 
[(array([1, 2, 3]), array([13, 14, 15])),
 (array([4, 5, 6]), array([16, 17, 18]))]

# pair them up (1, 13), (2, 14) ...
In [10]: create_final_pairings = [zip(*ele) for ele in intersting_pairs]

In [11]: create_final_pairings
Out[11]: [[(1, 13), (2, 14), (3, 15)], [(4, 16), (5, 17), (6, 18)]]

最后将all链接到一个单独的平面列表中并获得正确的顺序:

In [13]: from itertools import chain
# create flat list 
In [14]: flat_list = list(chain.from_iterable(zip(*create_final_pairings))

In [15]: flat_list
Out[15]: [(1, 13), (4, 16), (2, 14), (5, 17), (3, 15), (6, 18)]

使用zip转置的简单示例可能会有所帮助:

In [17]: l = [[1,2,3],[4,5,6]]

In [18]: zip(*l)
Out[18]: [(1, 4), (2, 5), (3, 6)]

In [19]: zip(*l)[0]
Out[19]: (1, 4)

In [20]: zip(*l)[1]
Out[20]: (2, 5)

In [21]: zip(*l)[2]
Out[21]: (3, 6)

对于 python2 ,您可以使用itertools.izip

from itertools import chain, izip


zipped = (izip(*ele) for ele in izip(*next(izip(*structure))))
print (list(chain.from_iterable(izip(*zipped))))

[(1, 13), (4, 16), (2, 14), (5, 17), (3, 15), (6, 18)]

答案 2 :(得分:2)

我必须首先编写非列表理解版本来解决这个问题:

new_training_vector = []
for m1, m2 in zip(structure[0], structure[1]):
    for t1, t2 in zip(m1, m2):
        for d1, d2 in zip(t1, t2):
            new_training_vector.append([d1, d2])

它的工作方式是创建两个并行迭代器(使用zip),每个模型一个,然后为每个训练集创建两个并行迭代器,依此类推,直到我们得到实际数据并且可以把它粘在一起。

一旦我们拥有了它,就不难将它折叠成列表理解:

new_training_vector = [[d1, d2]
                       for m1, m2 in zip(structure[0], structure[1])
                       for t1, t2 in zip(m1, m2)
                       for d1, d2 in zip(t1, t2)]

如果由于某种原因效果更好,您也可以使用字典执行此操作。你会丢失订单:

import collections
d = collections.defaultdict(list)
for model in structure:
    for i, training_set in enumerate(model):
        for j, row in enumerate(training_set):
            for k, point in enumerate(row):
                d[(i, j, k)].append(point)

这个的诀窍是我们只是跟踪我们看到每个点的位置(除了在模型级别),因此它们会自动进入相同的dict项目。

答案 3 :(得分:0)

我认为这就是你想要的格式,它使用生成器:

import numpy as np
structure = [[np.array([[1,2,3],[4,5,6]]), np.array([[7,8,9],[10,11,12]])], [np.array([[13,14,15],[16,17,18]]), np.array([[19,20,21],[22,23,24]])]]
struc = structure

my_gen = ([struc[i][j][k][l], struc[i+1][j][k][l]] for i in range(len(struc)-1)
                                     for j in range(len(struc[i]))
                                     for k in range(len(struc[i][j]))
                                     for l in range(len(struc[i][j][k])))

try:
    val = my_gen.next()
    while val != None:
        print val
        val = my_gen.next()
except:
    pass

import numpy as np structure = [[np.array([[1,2,3],[4,5,6]]), np.array([[7,8,9],[10,11,12]])], [np.array([[13,14,15],[16,17,18]]), np.array([[19,20,21],[22,23,24]])]] struc = structure my_gen = ([struc[i][j][k][l], struc[i+1][j][k][l]] for i in range(len(struc)-1) for j in range(len(struc[i])) for k in range(len(struc[i][j])) for l in range(len(struc[i][j][k]))) try: val = my_gen.next() while val != None: print val val = my_gen.next() except: pass