Слияние строк в NumPy для формирования нового массива - PullRequest
0 голосов
/ 25 июня 2018

Это пример того, чего я пытаюсь достичь.Я очень плохо знаком с Python и искал несколько часов, чтобы выяснить, что я делаю неправильно.Я не смог найти в чем моя проблема.Я все еще достаточно нов, чтобы искать неправильные фразы.Если да, не могли бы вы указать мне правильное направление?

Я хочу объединить n массивов массивов в один массив.Я хочу, чтобы первая строка из x была первой строкой в ​​комбинированном виде, первая строка из y - второй строкой объединенной, первая строка из z - третьей строкой, объединяла вторую строку в x в качестве четвертой строки вв сочетании и т. д., чтобы я выглядел примерно так:

x = [x1 x2 x3]
    [x4 x5 x6]
    [x7 x8 x9]

y = [y1 y2 y3]
    [y4 y5 y6]
    [y7 y8 y9]

x = [z1 z2 z3]
    [z4 z5 z6]
    [z7 z8 z9]

combined = [x1 x2 x3]
           [y1 y2 y3]
           [z1 z2 z3]
           [x4 x5 x6]
           [...]
           [z7 z8 z9]

Лучшее, что я могу придумать, это

    import numpy as np

x = np.random.rand(6,3)
y = np.random.rand(6,3)
z = np.random.rand(6,3)

combined = np.zeros((9,3))

for rows in range(len(x)):        
    combined[0::3] = x[rows,:] 
    combined[1::3] = y[rows,:]
    combined[2::3] = z[rows,:]


print(combined)

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

* Я просто понял, что это работает, но если кто-то знает метод более высокой производительности, * пожалуйста, дайте мне знать.

import numpy as np

x = np.random.rand(6,3) 
y = np.random.rand(6,3) 
z = np.random.rand(6,3)

combined = np.zeros((18,3))

for rows in range(6):        
  combined[rows*3,:] = x[rows,:] 
  combined[rows*3+1,:] = y[rows,:]
  combined[rows*3+2,:] = z[rows,:]

  print(combined)

Ответы [ 5 ]

0 голосов
/ 25 июня 2018

Простое решение numpy состоит в stack массивах на новой средней оси и преобразовании результата в 2d:

In [5]: x = np.arange(9).reshape(3,3)
In [6]: y = np.arange(9).reshape(3,3)+10
In [7]: z = np.arange(9).reshape(3,3)+100
In [8]: np.stack((x,y,z),axis=1).reshape(-1,3)
Out[8]: 
array([[  0,   1,   2],
       [ 10,  11,  12],
       [100, 101, 102],
       [  3,   4,   5],
       [ 13,  14,  15],
       [103, 104, 105],
       [  6,   7,   8],
       [ 16,  17,  18],
       [106, 107, 108]])

Может быть легче увидеть, что происходит, если мы дадим каждомуизмерение другого значения;например, 2 массива 3x4:

In [9]: x = np.arange(12).reshape(3,4)
In [10]: y = np.arange(12).reshape(3,4)+10

np.array объединяет их на новой 1-й оси, образуя массив 2x3x4.Чтобы получить чередование, которое вы хотите, мы можем транспонировать первые 2 измерения, получая 3x2x4.Затем измените форму до 6x4.

In [13]: np.array((x,y))
Out[13]: 
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[10, 11, 12, 13],
        [14, 15, 16, 17],
        [18, 19, 20, 21]]])
In [14]: np.array((x,y)).transpose(1,0,2)
Out[14]: 
array([[[ 0,  1,  2,  3],
        [10, 11, 12, 13]],

       [[ 4,  5,  6,  7],
        [14, 15, 16, 17]],

       [[ 8,  9, 10, 11],
        [18, 19, 20, 21]]])
In [15]: np.array((x,y)).transpose(1,0,2).reshape(-1,4)
Out[15]: 
array([[ 0,  1,  2,  3],
       [10, 11, 12, 13],
       [ 4,  5,  6,  7],
       [14, 15, 16, 17],
       [ 8,  9, 10, 11],
       [18, 19, 20, 21]])

np.vstack производит 6x4, но с неправильным порядком.Мы не можем транспонировать это напрямую.

np.stack с осью по умолчанию ведет себя так же, как np.array.Но с axis=1 создается 3x2x4, который мы можем изменить:

In [16]: np.stack((x,y), 1)
Out[16]: 
array([[[ 0,  1,  2,  3],
        [10, 11, 12, 13]],

       [[ 4,  5,  6,  7],
        [14, 15, 16, 17]],

       [[ 8,  9, 10, 11],
        [18, 19, 20, 21]]])

zip списка в принятом ответе - это версия списка transpose, создающая список 3 2-element tuples.

In [17]: list(zip(x,y))
Out[17]: 
[(array([0, 1, 2, 3]), array([10, 11, 12, 13])),
 (array([4, 5, 6, 7]), array([14, 15, 16, 17])),
 (array([ 8,  9, 10, 11]), array([18, 19, 20, 21]))]

np.array(list(zip(x,y))) производит то же самое, что и stack, массив 3x2x4.


Что касается скорости, я подозреваю, что выделение и назначение (как в ответе Эша) самый быстрый:

In [27]: z = np.zeros((6,4),int)
    ...: for i, arr in enumerate((x,y)):
    ...:     z[i::2,:] = arr
    ...:     
In [28]: z
Out[28]: 
array([[ 0,  1,  2,  3],
       [10, 11, 12, 13],
       [ 4,  5,  6,  7],
       [14, 15, 16, 17],
       [ 8,  9, 10, 11],
       [18, 19, 20, 21]])

Для серьезных сроков, используйте гораздо большие примеры, чем этот.

0 голосов
/ 25 июня 2018

Использование только векторизованных операций:

A = np.vstack((x, y, z))
idx = np.arange(A.shape[0]).reshape(-1, x.shape[0]).T.flatten()

A = A[idx]

Вот демоверсия:

import numpy as np

x, y, z = np.random.rand(3,3), np.random.rand(3,3), np.random.rand(3,3)

print(x, y, z)

[[ 0.88259564  0.17609363  0.01067734]
 [ 0.50299357  0.35075811  0.47230915]
 [ 0.751129    0.81839586  0.80554345]]
[[ 0.09469396  0.33848691  0.51550685]
 [ 0.38233976  0.05280427  0.37778962]
 [ 0.7169351   0.17752571  0.49581777]]
[[ 0.06056544  0.70273453  0.60681583]
 [ 0.57830566  0.71375038  0.14446909]
 [ 0.23799775  0.03571076  0.26917939]]

A = np.vstack((x, y, z))
idx = np.arange(A.shape[0]).reshape(-1, x.shape[0]).T.flatten()

print(idx)  # [0 3 6 1 4 7 2 5 8]

A = A[idx]

print(A)

[[ 0.88259564  0.17609363  0.01067734]
 [ 0.09469396  0.33848691  0.51550685]
 [ 0.06056544  0.70273453  0.60681583]
 [ 0.50299357  0.35075811  0.47230915]
 [ 0.38233976  0.05280427  0.37778962]
 [ 0.57830566  0.71375038  0.14446909]
 [ 0.751129    0.81839586  0.80554345]
 [ 0.7169351   0.17752571  0.49581777]
 [ 0.23799775  0.03571076  0.26917939]]
0 голосов
/ 25 июня 2018

Я немного изменил ваш код, чтобы получить желаемый результат

import numpy as np

x = np.random.rand(6,3)
y = np.random.rand(6,3)
z = np.random.rand(6,3)

combined = np.zeros((18,3))

combined[0::3] = x
combined[1::3] = y
combined[2::3] = z

print(combined)

У вас неправильная форма объединенной матрицы, и нет необходимости в цикле for.

0 голосов
/ 25 июня 2018

Возможно, это не самый питонский способ сделать это, но вы могли бы

for block in range(len(combined)/3):
    for rows in range(len(x)):

    combined[block*3+0::3] = x[rows,:] 
    combined[block*3+1::3] = y[rows,:]
    combined[block*3+2::3] = z[rows,:]
0 голосов
/ 25 июня 2018

Вы можете сделать это, используя понимание списка и zip:

combined = np.array([row for row_group in zip(x, y, z) for row in row_group])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...