Как добавить дополнительный столбец в массив NumPy - PullRequest
249 голосов
/ 13 декабря 2011

Допустим, у меня есть массив NumPy, a:

a = np.array([
    [1, 2, 3],
    [2, 3, 4]
    ])

И я хотел бы добавить столбец нулей, чтобы получить массив, b:

b = np.array([
    [1, 2, 3, 0],
    [2, 3, 4, 0]
    ])

Как я могу легко сделать это в NumPy?

Ответы [ 16 ]

272 голосов
/ 14 декабря 2011

np.r_[ ... ] и np.c_[ ... ] полезные альтернативы vstack и hstack, с квадратными скобками [] вместо круглых ().
Пара примеров:

: import numpy as np
: N = 3
: A = np.eye(N)

: np.c_[ A, np.ones(N) ]              # add a column
array([[ 1.,  0.,  0.,  1.],
       [ 0.,  1.,  0.,  1.],
       [ 0.,  0.,  1.,  1.]])

: np.c_[ np.ones(N), A, np.ones(N) ]  # or two
array([[ 1.,  1.,  0.,  0.,  1.],
       [ 1.,  0.,  1.,  0.,  1.],
       [ 1.,  0.,  0.,  1.,  1.]])

: np.r_[ A, [A[1]] ]              # add a row
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 0.,  1.,  0.]])
: # not np.r_[ A, A[1] ]

: np.r_[ A[0], 1, 2, 3, A[1] ]    # mix vecs and scalars
  array([ 1.,  0.,  0.,  1.,  2.,  3.,  0.,  1.,  0.])

: np.r_[ A[0], [1, 2, 3], A[1] ]  # lists
  array([ 1.,  0.,  0.,  1.,  2.,  3.,  0.,  1.,  0.])

: np.r_[ A[0], (1, 2, 3), A[1] ]  # tuples
  array([ 1.,  0.,  0.,  1.,  2.,  3.,  0.,  1.,  0.])

: np.r_[ A[0], 1:4, A[1] ]        # same, 1:4 == arange(1,4) == 1,2,3
  array([ 1.,  0.,  0.,  1.,  2.,  3.,  0.,  1.,  0.])

(причина в квадратных скобках [] вместо круглых () является то, что Python расширяется, например, 1: 4 в квадрате - чудеса перегрузки.)

152 голосов
/ 13 декабря 2011

Я думаю, что более простое решение и более быстрая загрузка состоит в следующем:

import numpy as np
N = 10
a = np.random.rand(N,N)
b = np.zeros((N,N+1))
b[:,:-1] = a

И время:

In [23]: N = 10

In [24]: a = np.random.rand(N,N)

In [25]: %timeit b = np.hstack((a,np.zeros((a.shape[0],1))))
10000 loops, best of 3: 19.6 us per loop

In [27]: %timeit b = np.zeros((a.shape[0],a.shape[1]+1)); b[:,:-1] = a
100000 loops, best of 3: 5.62 us per loop
129 голосов
/ 19 декабря 2013

Использование numpy.append:

>>> a = np.array([[1,2,3],[2,3,4]])
>>> a
array([[1, 2, 3],
       [2, 3, 4]])

>>> z = np.zeros((2,1), dtype=int64)
>>> z
array([[0],
       [0]])

>>> np.append(a, z, axis=1)
array([[1, 2, 3, 0],
       [2, 3, 4, 0]])
48 голосов
/ 13 декабря 2011

В одну сторону, используя hstack , это:

b = np.hstack((a, np.zeros((a.shape[0], 1), dtype=a.dtype)))
32 голосов
/ 13 августа 2013

Я считаю следующее самое элегантное:

b = np.insert(a, 3, values=0, axis=1) # Insert values before column 3

Преимущество insert заключается в том, что он также позволяет вставлять столбцы (или строки) в другие места массива. Также вместо вставки одного значения вы можете легко вставить целый вектор, например, дублировать последний столбец:

b = np.insert(a, insert_index, values=a[:,2], axis=1)

Что приводит к:

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

Что касается времени, insert может быть медленнее, чем решение Джоша Аделя:

In [1]: N = 10

In [2]: a = np.random.rand(N,N)

In [3]: %timeit b = np.hstack((a, np.zeros((a.shape[0], 1))))
100000 loops, best of 3: 7.5 µs per loop

In [4]: %timeit b = np.zeros((a.shape[0], a.shape[1]+1)); b[:,:-1] = a
100000 loops, best of 3: 2.17 µs per loop

In [5]: %timeit b = np.insert(a, 3, values=0, axis=1)
100000 loops, best of 3: 10.2 µs per loop
27 голосов
/ 26 сентября 2013

Я думаю:

np.column_stack((a, zeros(shape(a)[0])))

элегантнее.

26 голосов
/ 24 октября 2016

Меня также заинтересовал этот вопрос, и я сравнил скорость

numpy.c_[a, a]
numpy.stack([a, a]).T
numpy.vstack([a, a]).T
numpy.ascontiguousarray(numpy.stack([a, a]).T)               
numpy.ascontiguousarray(numpy.vstack([a, a]).T)
numpy.column_stack([a, a])
numpy.concatenate([a[:,None], a[:,None]], axis=1)
numpy.concatenate([a[None], a[None]], axis=0).T

, которая делает то же самое для любого входного вектора a.Время роста a:

enter image description here

Обратите внимание, что все несмежные варианты (в частности stack / vstack) в конечном итоге быстрее, чемвсе смежные варианты.column_stack (для его ясности и скорости), кажется, хороший вариант, если вам требуется смежность.


Код для воспроизведения сюжета:

import numpy
import perfplot

perfplot.show(
    setup=lambda n: numpy.random.rand(n),
    kernels=[
        lambda a: numpy.c_[a, a],
        lambda a: numpy.ascontiguousarray(numpy.stack([a, a]).T),
        lambda a: numpy.ascontiguousarray(numpy.vstack([a, a]).T),
        lambda a: numpy.column_stack([a, a]),
        lambda a: numpy.concatenate([a[:, None], a[:, None]], axis=1),
        lambda a: numpy.ascontiguousarray(numpy.concatenate([a[None], a[None]], axis=0).T),
        lambda a: numpy.stack([a, a]).T,
        lambda a: numpy.vstack([a, a]).T,
        lambda a: numpy.concatenate([a[None], a[None]], axis=0).T,
        ],
    labels=[
        'c_', 'ascont(stack)', 'ascont(vstack)', 'column_stack', 'concat',
        'ascont(concat)', 'stack (non-cont)', 'vstack (non-cont)',
        'concat (non-cont)'
        ],
    n_range=[2**k for k in range(20)],
    xlabel='len(a)',
    logx=True,
    logy=True,
    )
11 голосов
/ 27 января 2016

np.concatenate также работает

>>> a = np.array([[1,2,3],[2,3,4]])
>>> a
array([[1, 2, 3],
       [2, 3, 4]])
>>> z = np.zeros((2,1))
>>> z
array([[ 0.],
       [ 0.]])
>>> np.concatenate((a, z), axis=1)
array([[ 1.,  2.,  3.,  0.],
       [ 2.,  3.,  4.,  0.]])
8 голосов
/ 13 марта 2017

Предполагая, что M является (100,3) ndarray, а y является (100,) ndarray append, может использоваться следующим образом:

M=numpy.append(M,y[:,None],1)

Хитрость заключается в использовании

y[:, None]

Конвертирует y в (100, 1) 2D массив.

M.shape

теперь дает

(100, 4)
8 голосов
/ 28 декабря 2013

Мне нравится ответ Джоша Аделя из-за акцента на производительности.Незначительное улучшение производительности состоит в том, чтобы избежать накладных расходов на инициализацию с нулями, только чтобы быть перезаписанными.Это имеет измеримую разницу, когда N большое, вместо нулей используется пустое, а столбец нулей записывается как отдельный шаг:

In [1]: import numpy as np

In [2]: N = 10000

In [3]: a = np.ones((N,N))

In [4]: %timeit b = np.zeros((a.shape[0],a.shape[1]+1)); b[:,:-1] = a
1 loops, best of 3: 492 ms per loop

In [5]: %timeit b = np.empty((a.shape[0],a.shape[1]+1)); b[:,:-1] = a; b[:,-1] = np.zeros((a.shape[0],))
1 loops, best of 3: 407 ms per loop
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...