2015-11-23 5 views
2

Что такое эффективный способ преобразовать следующие Numpy массивы:Как изменить структуру массива?

a1 = \ 
[[ 1.1 -1.1 0.1] 
[ 2.1 -2.1 0.1] 
[ 3.1 -3.1 0.1] 
[ 4.1 -4.1 0.1] 
[ 5.1 -5.1 0.1]] 

и

a2 = \ 
[[ 1.2 -1.2 0.2] 
[ 2.2 -2.2 0.2] 
[ 3.2 -3.2 0.2] 
[ 4.2 -4.2 0.2] 
[ 5.2 -5.2 0.2]] 

в A:

[[[ 1.1 1.2] 
    [ 2.1 2.2] 
    [ 3.1 3.2] 
    [ 4.1 4.2] 
    [ 5.1 5.2]] 
[[-1.1 -1.2] 
    [-2.1 -2.2] 
    [-3.1 -3.2] 
    [-4.1 -4.2] 
    [-5.1 -5.2]] 
[[ 0.1 0.2] 
    [ 0.1 0.2] 
    [ 0.1 0.2] 
    [ 0.1 0.2] 
    [ 0.1 0.2]]] 

Есть ли способ сделать это без копирования данных (например, изменение значений в A также изменит соответствующие значения в a1 или a2)?

UPD. Вот один из принятых ответов и пути назад я использовал, - как копирование, наконец, обязательным:

import numpy as np 

a1 = [[ 1.1, -1.1, 0.1], 
     [ 2.1, -2.1, 0.1], 
     [ 3.1, -3.1, 0.1], 
     [ 4.1, -4.1, 0.1], 
     [ 5.1, -5.1, 0.1]] 
a1 = np.array(a1) 

a2 = [[ 1.2, -1.2, 0.2], 
     [ 2.2, -2.2, 0.2], 
     [ 3.2, -3.2, 0.2], 
     [ 4.2, -4.2, 0.2], 
     [ 5.2, -5.2, 0.2]] 
a2 = np.array(a2) 

a_expected = [[[ 1.1, 1.2], 
     [ 2.1, 2.2], 
     [ 3.1, 3.2], 
     [ 4.1, 4.2], 
     [ 5.1, 5.2]], 
    [[-1.1, -1.2], 
     [-2.1, -2.2], 
     [-3.1, -3.2], 
     [-4.1, -4.2], 
     [-5.1, -5.2]], 
    [[ 0.1, 0.2], 
     [ 0.1, 0.2], 
     [ 0.1, 0.2], 
     [ 0.1, 0.2], 
     [ 0.1, 0.2]]] 

npar = 2 

a = np.concatenate((a1[...,None].transpose(1,0,2), a2[...,None].transpose(1,0,2)), npar) 
assert np.all(a == a_expected) 

new_a1 = a.transpose(2, 1, 0)[0] 
new_a2 = a.transpose(2, 1, 0)[1] 

assert np.all(new_a1 == a1) 
assert np.all(new_a2 == a2) 
+0

В общем случае, заданные 'a1' и' a2', невозможно создать 'A' без копирования. Каждый массив NumPy содержит указатель на начало непрерывного блока памяти. Затем он использует strides, shape и dtype для определения значений в массиве. Если базовые данные в 'a1' и' a2' не являются частью одного непрерывного блока памяти, нет никакого способа присоединиться к ним - без копирования - в один новый массив NumPy, 'A', поскольку новый массив может имеют только * один указатель *, один шаг, одну форму и один тип dtype. – unutbu

ответ

2

Один подход с ndarray.transpose и np.concatenate -

np.concatenate((a1[...,None].transpose(1,0,2),a2[...,None].transpose(1,0,2)),2) 

Другой с ndarray.T и np.concatenate -

np.concatenate((a1.T[...,None],a2.T[...,None]),2) 

Конечный компактный с ndarray.transpose и np.dstack -

np.dstack((a1,a2)).transpose(1,0,2) 

время выполнения тестов -

In [63]: a1 = np.random.rand(500,300) 
    ...: a2 = np.random.rand(500,300) 
    ...: 

In [64]: %timeit np.concatenate((a1[...,None].transpose(1,0,2),a2[...,None].transpose(1,0,2)),2) 
100 loops, best of 3: 3.02 ms per loop 

In [65]: %timeit np.concatenate((a1.T[...,None],a2.T[...,None]),2) 
100 loops, best of 3: 3.03 ms per loop 

In [66]: %timeit np.dstack((a1,a2)).transpose(1,0,2) 
100 loops, best of 3: 3.05 ms per loop 

In [67]: a1 = np.random.rand(5000,3000) 
    ...: a2 = np.random.rand(5000,3000) 
    ...: 

In [68]: %timeit np.concatenate((a1[...,None].transpose(1,0,2),a2[...,None].transpose(1,0,2)),2) 
1 loops, best of 3: 372 ms per loop 

In [69]: %timeit np.concatenate((a1.T[...,None],a2.T[...,None]),2) 
1 loops, best of 3: 373 ms per loop 

In [70]: %timeit np.dstack((a1,a2)).transpose(1,0,2) 
1 loops, best of 3: 371 ms per loop 

Похоже, ни один был бы хорошим выбором.

Смежные вопросы