如何向NumPy数组添加额外的列

Pet*_*mit 271 python numpy

假设我有一个NumPy数组,a:

a = np.array([
    [1, 2, 3],
    [2, 3, 4]
    ])
Run Code Online (Sandbox Code Playgroud)

我想添加一列零来获取数组b:

b = np.array([
    [1, 2, 3, 0],
    [2, 3, 4, 0]
    ])
Run Code Online (Sandbox Code Playgroud)

我怎样才能在NumPy中轻松完成这项工作?

den*_*nis 291

np.r_[ ... ]并且np.c_[ ... ] 是有用的替代vstackhstack,用方括号[]代替圆().
几个例子:

: 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.])
Run Code Online (Sandbox Code Playgroud)

(方括号[]而不是round()的原因是Python扩展为例如1:4的正方形 - 超载的奇迹.)

  • 只是在寻找有关这方面的信息,最终这是一个比接受的更好的答案,因为它涵盖了在开头和结尾添加一个额外的列,而不仅仅是在其他答案的最后 (7认同)
  • @ Ay0我正在寻找一种方法,可以同时在所有层上批量添加偏置单元给我的人工神经网络,这是一个完美的答案. (2认同)
  • @Riley,你能举个例子吗?Python 3 具有“可迭代解包”,例如`np.c_[ * iterable ]`;请参阅 [表达式列表](https://docs.python.org/3.7/reference/expressions.html#expression-lists) 。 (2认同)

Jos*_*del 164

我认为更直接的解决方案和更快的启动是执行以下操作:

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

和时间:

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
Run Code Online (Sandbox Code Playgroud)

  • 我只是说你的答案对我的数据不起作用 (24认同)
  • 我想将(985,1)形状np araay追加到(985,2)np数组以使其成为(985,3)np数组,但它不起作用.我得到"无法从形状(985)广播输入数组到形状(985,1)"错误.我的代码出了什么问题?代码:np.hstack(data,data1) (15认同)
  • @Outlier你应该发一个新问题,而不是在这个问题的评论中问一个. (4认同)
  • @JoshAdel:我在ipython上尝试了你的代码,我觉得有一个语法错误.您可能想尝试将`a = np.random.rand((N,N))`更改为`a = np.random.rand(N,N)` (4认同)
  • 这只是执行附加、插入或堆栈时的一个技巧。并且不应被接受为答案。工程师应考虑使用以下答案。 (2认同)

小智 136

用途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]])
Run Code Online (Sandbox Code Playgroud)

  • 这比@JoshAdel的答案更直接,但在处理大型数据集时,它更慢.我会根据可读性的重要性在两者之间进行选择. (4认同)
  • 插入更复杂的列时这很好. (2认同)
  • `append`实际上只是调用`concatenate` (2认同)

Pet*_*mit 47

使用hstack的一种方法是:

b = np.hstack((a, np.zeros((a.shape[0], 1), dtype=a.dtype)))
Run Code Online (Sandbox Code Playgroud)

  • 我认为这是最优雅的解决方案。 (3认同)
  • 删除`dtype`参数,不需要甚至不允许.虽然您的解决方案足够优雅,但如果您需要经常"追加"到阵列,请注意不要使用它.如果你不能一次创建整个数组并在以后填充它,那么创建一个数组列表并立即`hstack`. (3认同)
  • +1 - 我就是这样做的 - 你打败我把它作为答案发布:). (2认同)
  • @eumiro我不确定我是如何设法在错误的位置获取dtype的,但是np.zeros需要一个dtype来避免所有东西变成float(而a是int) (2认同)

Bjö*_*örn 36

我发现以下最优雅:

b = np.insert(a, 3, values=0, axis=1) # Insert values before column 3
Run Code Online (Sandbox Code Playgroud)

一个优点insert是它还允许您在数组内的其他位置插入列(或行).此外,您可以轻松插入整个矢量,而不是插入单个值,例如复制最后一列:

b = np.insert(a, insert_index, values=a[:,2], axis=1)
Run Code Online (Sandbox Code Playgroud)

这导致:

array([[1, 2, 3, 3],
       [2, 3, 4, 4]])
Run Code Online (Sandbox Code Playgroud)

对于时机,insert可能比JoshAdel的解决方案慢:

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
Run Code Online (Sandbox Code Playgroud)

  • @ThomasAhle您可以通过使用`a.shape [axis]`获取该轴上的大小来追加行或列。即 对于追加行,执行`np.insert(a,a.shape [0],999,axis = 0)`,对于列,执行`np.insert(a,a.shape [1],999) ,axis = 1)`。 (2认同)

Nic*_*mer 29

我也对这个问题感兴趣并比较了它的速度

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
Run Code Online (Sandbox Code Playgroud)

这对于任何输入向量都做同样的事情a.成长时间a:

在此输入图像描述

请注意,所有非连续变体(特别是 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,
    )
Run Code Online (Sandbox Code Playgroud)

  • 不错的图表!只是想您想知道在幕后,“stack”、“hstack”、“vstack”、“column_stack”、“dstack”都是构建在“np.concatenate”之上的辅助函数。通过追踪[堆栈的定义](https://github.com/numpy/numpy/blob/master/numpy/core/shape_base.py#L296)我发现`np.stack([a,a]) ` 正在调用 `np.concatenate([a[None], a[None]], axis=0)`。将 `np.concatenate([a[None], a[None]], axis=0).T` 添加到 perfplot 中可能会很好,以表明 `np.concatenate` 始终至少与其一样快辅助功能。 (4认同)
  • 哇,喜欢这些情节! (2认同)
  • 似乎对于将列追加到数组的递归操作,例如 b = [b, a],某些命令不起作用(引发有关不等维度的错误)。唯一两个似乎适用于大小不等的数组(即当一个是矩阵而另一个是一维向量时)是“c_”和“column_stack” (2认同)

小智 27

我认为:

np.column_stack((a, zeros(shape(a)[0])))
Run Code Online (Sandbox Code Playgroud)

更优雅.


han*_*luc 12

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.]])
Run Code Online (Sandbox Code Playgroud)


小智 11

将额外的列添加到 numpy 数组:

Numpy 的np.append方法接受三个参数,前两个是 2D numpy 数组,第三个是轴参数,指示沿哪个轴附加:

import numpy as np  
x = np.array([[1,2,3], [4,5,6]]) 
print("Original x:") 
print(x) 

y = np.array([[1], [1]]) 
print("Original y:") 
print(y) 

print("x appended to y on axis of 1:") 
print(np.append(x, y, axis=1)) 
Run Code Online (Sandbox Code Playgroud)

印刷:

Original x:
[[1 2 3]
 [4 5 6]]
Original y:
[[1]
 [1]]
y appended to x on axis of 1:
[[1 2 3 1]
 [4 5 6 1]]
Run Code Online (Sandbox Code Playgroud)

  • 请注意,您在这里将 y 附加到 x,而不是将 x 附加到 y - 这就是为什么 y 的列向量位于结果中 x 列的右侧。 (3认同)

Roe*_*ven 10

假设M是(100,3)ndarray并且y是(100,)ndarray append可以如下使用:

M=numpy.append(M,y[:,None],1)
Run Code Online (Sandbox Code Playgroud)

诀窍是使用

y[:, None]
Run Code Online (Sandbox Code Playgroud)

这将转换y为(100,1)2D阵列.

M.shape
Run Code Online (Sandbox Code Playgroud)

现在给

(100, 4)
Run Code Online (Sandbox Code Playgroud)


小智 8

我喜欢JoshAdel的答案,因为他专注于表现.一个小的性能改进是避免用零初始化的开销,只是被覆盖.当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
Run Code Online (Sandbox Code Playgroud)


Tai*_*Tai 5

np.insert 也达到目的。

matA = np.array([[1,2,3], 
                 [2,3,4]])
idx = 3
new_col = np.array([0, 0])
np.insert(matA, idx, new_col, axis=1)

array([[1, 2, 3, 0],
       [2, 3, 4, 0]])
Run Code Online (Sandbox Code Playgroud)

它沿一个轴new_col在给定索引之前在此处插入值idx。换句话说,新插入的值将占据该idx列并向后移动原始位置idx

  • 请注意,“插入”不存在,因为人们可以假定给定函数名称(请参阅答案中链接的文档)。 (2认同)

Shi*_*n S 5

对我来说,下一个方法看起来非常直观和简单。

zeros = np.zeros((2,1)) #2 is a number of rows in your array.   
b = np.hstack((a, zeros))
Run Code Online (Sandbox Code Playgroud)