如何以有效的方式创建2D numpy数组的对应元素的元组

时间:2019-06-01 03:43:34

标签: python numpy

我有两个2D numpy数组,一个用于纬度,另一个用于经度。

a = [ [1, 2, 3, 4],                  b = [ [a, b, c, d],
      [1, 2, 3, 4],                        [a, b, c, d],
      [1, 2, 3, 4],                        [a, b, c, d],
      [1, 2, 3, 4] ]                       [a, b, c, d] ]

我想要以下2种输出(一个列表和一个2D元组数组)

output1 = [ (1,a), (2,a), (3,a), (4,a), (1,b), (2,b), (3,b), (4,b), . . . (3,d), (4,d) ]

output2 = [ [(1,a), (2,a), (3,a), (4,a)],
            [(1,b), (2,b), (3,b), (4,b)],
            [(1,c), (2,c), (3,c), (4,c)],
            [(1,d), (2,d), (3,d), (4,d)] ]

我应该如何有效地做到无循环?

这是 a b 生成的代码:

aa = np.array([1,2,3,4])
bb = np.array(['a','b','c','d'])
a, b = np.meshgrid(aa,bb)

3 个答案:

答案 0 :(得分:2)

不带numpy的解决方案

from itertools import chain
output2 = [list(zip(i,j)) for i,j in zip(a,zip(*b))]
output1 = list(chain.from_iterable(output2))

答案 1 :(得分:1)

您的2个数组:

In [88]: aa = np.array([1,2,3,4]) 
    ...: bb = np.array(['a','b','c','d']) 
    ...: a, b = np.meshgrid(aa,bb)                                                   
In [89]: a                                                                           
Out[89]: 
array([[1, 2, 3, 4],
       [1, 2, 3, 4],
       [1, 2, 3, 4],
       [1, 2, 3, 4]])
In [90]: b                                                                           
Out[90]: 
array([['a', 'a', 'a', 'a'],
       ['b', 'b', 'b', 'b'],
       ['c', 'c', 'c', 'c'],
       ['d', 'd', 'd', 'd']], dtype='<U1')

某些版本的concatenate可用于连接两个数组。 stack和第2轴一起完成,np.array((a,b))也跟着转置。

In [91]: np.stack((a,b),axis=2)                                                      
Out[91]: 
array([[['1', 'a'],
        ['2', 'a'],
        ['3', 'a'],
        ['4', 'a']],

       [['1', 'b'],
        ['2', 'b'],
        ['3', 'b'],
        ['4', 'b']],

       [['1', 'c'],
        ['2', 'c'],
        ['3', 'c'],
        ['4', 'c']],

       [['1', 'd'],
        ['2', 'd'],
        ['3', 'd'],
        ['4', 'd']]], dtype='<U21')

但是组合数组是字符串dtype,而不是整数和字符串的混合。而不是元组。这是一个(4,4,2)数组。

但是如果我们将数组转换为对象dtype:

In [93]: np.stack((a.astype(object),b.astype(object)),axis=2)                        
Out[93]: 
array([[[1, 'a'],
        [2, 'a'],
        [3, 'a'],
        [4, 'a']],

       [[1, 'b'],
        [2, 'b'],
       ...
        [4, 'd']]], dtype=object)

我们可以将其重塑为(-1,2),然后tolist()以产生列表版本。

或者我们可以创建一个结构化的数组,其中包含一个整数字段和一个字符串字段。其打印显示使用元组标记内部记录(与上面的最后一个大小2维不同)。

In [98]: arr = np.zeros(a.shape, dtype='int,U5')                                     
In [99]: arr                                                                         
Out[99]: 
array([[(0, ''), (0, ''), (0, ''), (0, '')],
       [(0, ''), (0, ''), (0, ''), (0, '')],
       [(0, ''), (0, ''), (0, ''), (0, '')],
       [(0, ''), (0, ''), (0, ''), (0, '')]],
      dtype=[('f0', '<i8'), ('f1', '<U5')])
In [100]: arr['f0']=a                                                                
In [101]: arr['f1']=b                                                                
In [102]: arr                                                                        
Out[102]: 
array([[(1, 'a'), (2, 'a'), (3, 'a'), (4, 'a')],
       [(1, 'b'), (2, 'b'), (3, 'b'), (4, 'b')],
       [(1, 'c'), (2, 'c'), (3, 'c'), (4, 'c')],
       [(1, 'd'), (2, 'd'), (3, 'd'), (4, 'd')]],
      dtype=[('f0', '<i8'), ('f1', '<U5')])

In [103]: print(arr)                                                                 
[[(1, 'a') (2, 'a') (3, 'a') (4, 'a')]
 [(1, 'b') (2, 'b') (3, 'b') (4, 'b')]
 [(1, 'c') (2, 'c') (3, 'c') (4, 'c')]
 [(1, 'd') (2, 'd') (3, 'd') (4, 'd')]]

zip列表理解可以很好地完成列表版本:

In [105]: [item for item in zip(a.flat,b.flat)]                                      
Out[105]: 
[(1, 'a'),
 (2, 'a'),
 (3, 'a'),
 (4, 'a'),
 (1, 'b'),
 ...
 (4, 'd')]

对于此样本大小,列表理解速度更快。尝试避免循环并不总是最有效的方法。

===

arr的元素是np.void对象,尽管它们显示为元组。要获取实际的元组,我们必须将其转换为list或object dtype:

In [109]: arr.tolist()                                                               
Out[109]: 
[[(1, 'a'), (2, 'a'), (3, 'a'), (4, 'a')],
 [(1, 'b'), (2, 'b'), (3, 'b'), (4, 'b')],
 [(1, 'c'), (2, 'c'), (3, 'c'), (4, 'c')],
 [(1, 'd'), (2, 'd'), (3, 'd'), (4, 'd')]]
In [110]: arr.astype(object)                                                         
Out[110]: 
array([[(1, 'a'), (2, 'a'), (3, 'a'), (4, 'a')],
       [(1, 'b'), (2, 'b'), (3, 'b'), (4, 'b')],
       [(1, 'c'), (2, 'c'), (3, 'c'), (4, 'c')],
       [(1, 'd'), (2, 'd'), (3, 'd'), (4, 'd')]], dtype=object)
In [111]: type(_[0,0])                                                               
Out[111]: tuple

可以通过名称访问结构化数组的字段:

In [112]: arr['f0']                                                                  
Out[112]: 
array([[1, 2, 3, 4],
       [1, 2, 3, 4],
       [1, 2, 3, 4],
       [1, 2, 3, 4]])

答案 2 :(得分:0)

使用numpy和tolist的矢量化方法:

a = np.array([[1,2,3,4],
              [1,2,3,4],
              [1,2,3,4],
              [1,2,3,4]])
b = np.array([[10,20,30,40],
              [10,20,30,40],
              [10,20,30,40],
              [10,20,30,40]])

x = np.stack((a,b), axis=-1)

x.reshape(4,4,2).tolist()
[[[1, 10], [2, 10], [3, 10], [4, 10]], 
 [[1, 20], [2, 20], [3, 20], [4, 20]], 
 [[1, 30], [2, 30], [3, 30], [4, 30]], 
 [[1, 40], [2, 40], [3, 40], [4, 40]]]

x.reshape(16,2).tolist()
[[1, 10], [2, 10], [3, 10], [4, 10], [1, 20], [2, 20], [3, 20], [4, 20], [1, 30], [2, 30], [3, 30], [4, 30], [1, 40], [2, 40], [3, 40], [4, 40]]