Zip-массивы в Python - PullRequest
       114

Zip-массивы в Python

0 голосов
/ 09 мая 2020

У меня есть один 2D-массив и один одномерный массив. Я хотел бы заархивировать их вместе.

import numpy as np

arr2D = [[5.88964708e-02, -2.38142395e-01, -4.95821417e-01, -7.07269274e-01],
         [0.53363666,  0.1654723 , -0.16439857, -0.44880487]]
arr2D = np.asarray(arr2D)

arr1D = np.arange(7, 8.5+0.5, 0.5)
arr1D = np.asarray(arr1D)

res = np.array(list(zip(arr1D, arr2D)))

print(res)

, что приводит к:

[[7.0 array([ 0.05889647, -0.2381424 , -0.49582142, -0.70726927])]
 [7.5 array([ 0.53363666,  0.1654723 , -0.16439857, -0.44880487])]]

Но я пытаюсь получить:

[[(7.0, 0.05889647), (7.5, -0.2381424), (8.0, -0.49582142), (8.5, -0.70726927)]]
[[(7.0, 0.53363666), (7.5, 0.1654723),(8.0, -0.16439857), (8.5, -0.44880487)]]

Как мне это сделать это?

Ответы [ 3 ]

2 голосов
/ 09 мая 2020

Вы были почти у цели! Вот решение:

list(map(lambda x: list(zip(arr1D, x)), arr2D))
[[(7.0, 0.0588964708),
  (7.5, -0.238142395),
  (8.0, -0.495821417),
  (8.5, -0.707269274)],
 [(7.0, 0.53363666), (7.5, 0.1654723), (8.0, -0.16439857), (8.5, -0.44880487)]]
1 голос
/ 09 мая 2020
In [382]: arr2D = [[5.88964708e-02, -2.38142395e-01, -4.95821417e-01, -7.07269274e-01], 
     ...:          [0.53363666,  0.1654723 , -0.16439857, -0.44880487]] 
     ...: arr2D = np.asarray(arr2D) 
     ...: arr1D = np.arange(7, 8.5+0.5, 0.5)   # already an array                                      


In [384]: arr2D.shape                                                                                  
Out[384]: (2, 4)
In [385]: arr1D.shape                                                                                  
Out[385]: (4,)

zip выполняет итерацию по первому измерению аргументов и останавливается на самом коротком:

In [387]: [[i,j[0:2]] for i,j in zip(arr1D, arr2D)]                                                    
Out[387]: 
[[7.0, array([ 0.05889647, -0.2381424 ])],
 [7.5, array([0.53363666, 0.1654723 ])]]

Если мы транспонируем 2d, то есть теперь (4,2), мы получить список из четырех элементов:

In [389]: [[i,j] for i,j in zip(arr1D, arr2D.T)]                                                       
Out[389]: 
[[7.0, array([0.05889647, 0.53363666])],
 [7.5, array([-0.2381424,  0.1654723])],
 [8.0, array([-0.49582142, -0.16439857])],
 [8.5, array([-0.70726927, -0.44880487])]]

Мы могли бы добавить еще один уровень итерации, чтобы получить желаемые пары:

In [390]: [[(i,k) for k in j] for i,j in zip(arr1D, arr2D.T)]                                          
Out[390]: 
[[(7.0, 0.0588964708), (7.0, 0.53363666)],
 [(7.5, -0.238142395), (7.5, 0.1654723)],
 [(8.0, -0.495821417), (8.0, -0.16439857)],
 [(8.5, -0.707269274), (8.5, -0.44880487)]]

и с идиомой транспонирования списка:

In [391]: list(zip(*_))                                                                                
Out[391]: 
[((7.0, 0.0588964708), (7.5, -0.238142395), (8.0, -0.495821417), (8.5, -0.707269274)),
 ((7.0, 0.53363666), (7.5, 0.1654723), (8.0, -0.16439857), (8.5, -0.44880487))]

Или мы можем получить этот результат напрямую, переместив zip во внутренний l oop:

[[(i,k) for i,k in  zip(arr1D, row)] for row in arr2D] 

Другими словами, вы объединяете элементы arr1D с элементами каждого строка 2D, а не целая строка.

Поскольку у вас уже есть массивы, одно из решений массива может быть лучше, но я пытаюсь прояснить, что происходит с zip.

numpy

Существуют различные способы построения массива numpy из этих массивов. Поскольку вы хотите повторить значения arr1D:

Этот repeat создает массив (4,2), который соответствует arr2D (tile также работает):

In [400]: arr1D[None,:].repeat(2,0)                                                                    
Out[400]: 
array([[7. , 7.5, 8. , 8.5],
       [7. , 7.5, 8. , 8.5]])
In [401]: arr2D                                                                                        
Out[401]: 
array([[ 0.05889647, -0.2381424 , -0.49582142, -0.70726927],
       [ 0.53363666,  0.1654723 , -0.16439857, -0.44880487]])

который затем может быть соединен на новой задней оси:

In [402]: np.stack((_400, arr2D), axis=2)                                                              
Out[402]: 
array([[[ 7.        ,  0.05889647],
        [ 7.5       , -0.2381424 ],
        [ 8.        , -0.49582142],
        [ 8.5       , -0.70726927]],

       [[ 7.        ,  0.53363666],
        [ 7.5       ,  0.1654723 ],
        [ 8.        , -0.16439857],
        [ 8.5       , -0.44880487]]])

Или структурированный массив с отображением в виде кортежа:

In [406]: arr = np.zeros((2,4), dtype='f,f')                                                           
In [407]: arr                                                                                          
Out[407]: 
array([[(0., 0.), (0., 0.), (0., 0.), (0., 0.)],
       [(0., 0.), (0., 0.), (0., 0.), (0., 0.)]],
      dtype=[('f0', '<f4'), ('f1', '<f4')])
In [408]: arr['f1'] = arr2D                                                                            
In [409]: arr['f0'] = _400                                                                             
In [410]: arr                                                                                          
Out[410]: 
array([[(7. ,  0.05889647), (7.5, -0.2381424 ), (8. , -0.49582142),
        (8.5, -0.70726925)],
       [(7. ,  0.5336367 ), (7.5,  0.1654723 ), (8. , -0.16439857),
        (8.5, -0.44880486)]], dtype=[('f0', '<f4'), ('f1', '<f4')])
1 голос
/ 09 мая 2020

Вы можете использовать numpy .tile для расширения 1d-массива, а затем использовать numpy .dstack , а именно:

import numpy as np

arr2D = np.array([[5.88964708e-02, -2.38142395e-01, -4.95821417e-01, -7.07269274e-01], 
                  [0.53363666,  0.1654723 , -0.16439857, -0.44880487]])
arr1D = np.arange(7, 8.5+0.5, 0.5)

np.dstack([np.tile(arr1D, (2,1)), arr2D])
array([[[ 7.        ,  0.05889647],
        [ 7.5       , -0.2381424 ],
        [ 8.        , -0.49582142],
        [ 8.5       , -0.70726927]],

       [[ 7.        ,  0.53363666],
        [ 7.5       ,  0.1654723 ],
        [ 8.        , -0.16439857],
        [ 8.5       , -0.44880487]]])
...