#arrays #numpy
#массивы #numpy
Вопрос:
Предположим, что задан одномерный массив A
. Есть ли простой способ построить 3D-массив, B
такой, чтобы B[i,j,k] = A[k]
для всех i, j, k? Можно предположить, что форма B задана, и это B.shape[2] = A.shape[0]
.
Комментарии:
1. Вы имеете в виду, что хотите разбить массив на плитки? docs.scipy.org/doc/numpy/reference/generated/numpy.tile.html
Ответ №1:
>>> k = 4
>>> a = np.arange(k)
>>> j = 3
>>> i = 2
>>> np.tile(a,j*i).reshape((i,j,k))
array([[[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3]],
[[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3]]]
Комментарии:
1. Вы можете заменить
np.tile(np.tile(a,j),i).reshape((i,j,k))
наnp.tile(a, i*j).reshape((i,j,k))
2. Я удалил свое
np.tile(A,(i,j,1))
предложение, потому что у него была ужасная производительность для больших массивов. Знаете, почемуnp.tile(A,i*j).reshape(i,j,k)
масштабируется намного лучше?3. @MLW: Я набрал
numpy.source(numpy.tile)
и увидел, что этоtile
вызываетreshape
иrepeat
для каждого элемента вreps
кортеже.reshape
возвращает копию, что означает перераспределение всей этой памяти каждый раз. Мне кажется плохо реализованным.
Ответ №2:
Еще один простой способ сделать это — простое назначение — трансляция автоматически выполнит правильные действия:
i = 2
j = 3
k = 4
a = numpy.arange(k)
b = numpy.empty((i, j, k))
b[:] = a
print b
С принтами
[[[ 0. 1. 2. 3.]
[ 0. 1. 2. 3.]
[ 0. 1. 2. 3.]]
[[ 0. 1. 2. 3.]
[ 0. 1. 2. 3.]
[ 0. 1. 2. 3.]]]
Ответ №3:
for k,v in enumerate(A): B[:,:,k] = v
Комментарии:
1. Разве это не очень неэффективно, поскольку включает медленный цикл for?
2. @celli Размер этого массива равен O (n)
A
, и ни один алгоритм не может сделать это лучше, потому что каждый элементA
должен быть проверен для выполнения вычисления. В других ответах предполагалось, что использованиеnumppy.tile()
является лучшим вариантом, чем прямое присвоение. Решение, которое я предлагаю, является ясным и pythonic, и я ожидаю, что NumPy эффективно обработает назначения (возможно, сtile()
), но нужно было бы измерить (время), чтобы знать.