Как эффективно создать кортеж из соответствующих элементов двумерного массива - PullRequest
0 голосов
/ 01 июня 2019

У меня есть два двумерных массива, один для широты, другой для долготы.

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 вида выходных данных (список и двумерный массив кортежей)

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 ]

2 голосов
/ 01 июня 2019

раствор без комков

from itertools import chain
output2 = [list(zip(i,j)) for i,j in zip(a,zip(*b))]
output1 = list(chain.from_iterable(output2))
1 голос
/ 01 июня 2019

Ваши 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')

Но объединенный массив - это строка типа d, а не смесь целых чисел и строк. И не кортежи. Это массив (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 объектами, хотя они отображаются как кортежи. Чтобы получить реальные кортежи, мы должны преобразовать их в 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]])
0 голосов
/ 01 июня 2019

Векторизованный подход с использованием 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]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...