Подтвердить что ты не робот

Вставьте 0s в массив 2d

У меня есть массив x:

x = [0, -1, 0, 3]

и я хочу y:

y = [[0, -2, 0, 2],
     [0, -1, 0, 3],
     [0,  0, 0, 4]]

где первая строка x-1, вторая строка x, а третья строка - x+1. Все четные индексы столбцов равны нулю.

Я делаю:

y=np.vstack(x-1, x, x+1)
y[0][::2] = 0
y[1][::2] = 0
y[2][::2] = 0

Я думал, что это может быть однострочный, вместо 4.

4b9b3361

Ответ 1

В двух строках

>>> x = np.array([0, -1, 0, 3])
>>> y = np.vstack((x-1, x, x+1))
>>> y[:,::2] = 0
>>> y
array([[ 0, -2,  0,  2],
       [ 0, -1,  0,  3],
       [ 0,  0,  0,  4]])

Описание

y[:, ::2]

дает полное первое измерение. т.е. все строки и каждая другая запись образуют второе измерение, то есть столбцы:

array([[-1, -1],
       [ 0,  0],
       [ 1,  1]])

Это отличается от:

y[:][::2]

потому что это работает в два этапа. Шаг первый:

y[:]

дает представление обо всем массиве:

array([[-1, -2, -1,  2],
       [ 0, -1,  0,  3],
       [ 1,  0,  1,  4]])

Поэтому второй шаг делает это в основном:

y[::2]
array([[-1, -2, -1,  2],
       [ 1,  0,  1,  4]])

Он работает по первому измерению. т.е. строки.

Ответ 2

Или, наоборот, используйте broadcasting:

import numpy as np

x = np.array([0, -1, 0, 3])
delta = np.array([-1, 0, 1])
y = x + delta[:, None]
y[:, ::2] = 0

print(repr(y))
# array([[ 0, -2,  0,  2],
#        [ 0, -1,  0,  3],
#        [ 0,  0,  0,  4]])
  • delta указывает, сколько добавить/вычесть из каждой строки
  • Индексирование с помощью None вставляет новое измерение размера 1
  • delta[:, None].shape == (3, 1) и x.shape == (4,), поэтому результат x + delta[:, None] передается в массив (3, 4)
  • Наконец, y[:, ::2] = 0 заполняет каждый столбец нулями.

Ответ 3

Используя вещание NumPy для однострочного -

(np.arange(x.size)%2)*(x + np.array([-1,0,1])[:,None])

Объяснение -

  • np.arange(x.size)%2) дает нам чередующиеся 0s и 1s.
  • Используйте трансляцию с помощью x + np.array([-1,0,1])[:,None]), чтобы получить суммы в векторном виде.
  • Используйте переменные 1s и 0s, созданные в step-1, чтобы установить или не установить столбцы суммированного массива на этапе 2 и, таким образом, получить окончательный вывод.

Пример прогона -

In [40]: x
Out[40]: array([ 0, -1,  0,  3])

In [41]: (np.arange(x.size)%2)*(x + np.array([-1,0,1])[:,None])
Out[41]: 
array([[ 0, -2,  0,  2],
       [ 0, -1,  0,  3],
       [ 0,  0,  0,  4]])

Ответ 4

Однострочный без numpy:

x = [0, -1, 0, 3]
y = [ [(x[i] - j if i%2 else 0) for i in range(4)] for j in (1,0,-1)]

дает следующий y:

[[0, -2, 0, 2], [0, -1, 0, 3], [0,  0, 0, 4]]

Ответ 5

Лично я бы рассматривал это по-другому. Вы не добавляете 1 в x, вы добавляете [0, 1, 0, 1].

x = np.array([0, -1, 0, 3])
d = np.resize([0, 1], len(x))
y = np.vstack((x-d, x, x+d))

Ответ 6

Один лайнер в NumPy:

>>> x = np.array([0, -1, 0, 3])
>>> y = np.vstack((x-1, x, x+1)) * np.resize([0, 1], len(x))
>>> y
array([[ 0, -2,  0,  2],
       [ 0, -1,  0,  3],
       [ 0,  0,  0,  4]])

Ответ 7

короткая версия: [[-1],[0],[1]]*(x!=0)+x.

[[-1],[0],[1]]*(x!=0) является

     |-1                                    |-1                   | 0 -1 0 -1 |
dot( |0  , [True False True False] ) = dot( |0  ,  [ 1 0 1 0] ) = | 0  0 0  0 |  = z
     |1                                     |1                    | 0  1 0  1 |

z + x: (braodcasting)

| 0 -1 0 -1 |   | 0 -1 0 3 |    | 0 -2 0 2 |
| 0  0 0  0 | + | 0 -1 0 3 |  = | 0 -1 0 3 |
| 0  1 0  1 |   | 0 -1 0 3 |    | 0  0 0 4 |