numpy-将行添加到数组


161

如何将行添加到numpy数组?

我有一个数组A:

A = array([[0, 1, 2], [0, 2, 0]])

如果X中每行的第一个元素满足特定条件,我希望从另一个数组X向该数组添加行。

Numpy数组没有像列表那样的“追加”方法,或者看起来。

如果A和X是列表,我只会这样做:

for i in X:
    if i[0] < 3:
        A.append(i)

是否有numpythonic的方式来做等效的?

谢谢,S ;-)


Answers:


120

什么X啊 如果它是一个二维数组,你怎么能那么其行比作一个号码:i < 3

OP评论后编辑:

A = array([[0, 1, 2], [0, 2, 0]])
X = array([[0, 1, 2], [1, 2, 0], [2, 1, 2], [3, 2, 0]])

AX第一个元素添加到所有行< 3

import numpy as np
A = np.vstack((A, X[X[:,0] < 3]))

# returns: 
array([[0, 1, 2],
       [0, 2, 0],
       [0, 1, 2],
       [1, 2, 0],
       [2, 1, 2]])

1
不好意思!假设一个2D数组,其每行的第一个元素必须满足条件。我将对其进行编辑。谢谢,S ;-)
达伦·J·菲茨帕特里克

2
@ DarrenJ.Fitzpatrick请记住,通过执行这种类型的操作,您会与Numpy所做的出色工作背道而驰,Numpy会为现有数组预先分配内存A。显然,对于像此答案这样的小问题,这不是问题,但是对于大数据来说可能会更麻烦。
dtlussier 2011年

166

好吧,你可以这样做:

  newrow = [1,2,3]
  A = numpy.vstack([A, newrow])

2
@Kris为什么不推荐使用?我在文档
Georgy

1
@乔治说实话,我不知道。我在这里寻找与您相同的答案:-)。我现在不记得为什么我写上面的评论了。我一定在文档中看到过时了。但是现在看文档...并没有这么说。他们是否有可能不赞成使用它,然后再次改变主意,认为对于太多的人而言,过分弃用它会太烦人了?
克里斯(Kris)

32

由于这个问题已经存在了7年,所以我使用的最新版本是numpy版本1.13和python3,我在向矩阵中添加一行时也做同样的事情,请记住在第二个参数中加上双括号,否则会引起尺寸误差。

在这里我要添加矩阵A

1 2 3
4 5 6

连续

7 8 9

相同的用法 np.r_

A= [[1, 2, 3], [4, 5, 6]]
np.append(A, [[7, 8, 9]], axis=0)

    >> array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])
#or 
np.r_[A,[[7,8,9]]]

只是对某人感兴趣,如果您想添加一列,

array = np.c_[A,np.zeros(#A's row size)]

按照我们之前在矩阵A上所做的操作,向其中添加一列

np.c_[A, [2,8]]

>> array([[1, 2, 3, 2],
          [4, 5, 6, 8]])

10

您也可以这样做:

newrow = [1,2,3]
A = numpy.concatenate((A,newrow))

2
嗯。当我尝试此操作时,它只是添加到A的末尾,而不是按照OP请求添加新行。
Todd Curry 2013年

13
可能np.concatenate((A,newrow), axis=0)
Konstantinos Roditakis 2014年

3
从numpy版本开始1.12.1(在Python 3中),似乎试图将向量连接到矩阵上引发上ValueError: all the input arrays must have same number of dimensions。看起来它希望向量在愿意连接之前明确地重塑为列或行向量。
MRule

3
@MRule可以按照@Flora PJ Li stackoverflow.com/a/47845065/1410035的答案使用双方括号来解决。 newrow = [[1,2,3]]
汤姆·萨利巴

10

如果每行之后都不需要进行计算,则在python中添加行然后转换为numpy会更快。以下是使用python 3.6与numpy 1.14进行的时序测试,添加了100行,一次添加一行:

import numpy as np 
from time import perf_counter, sleep

def time_it():
    # Compare performance of two methods for adding rows to numpy array
    py_array = [[0, 1, 2], [0, 2, 0]]
    py_row = [4, 5, 6]
    numpy_array = np.array(py_array)
    numpy_row = np.array([4,5,6])
    n_loops = 100

    start_clock = perf_counter()
    for count in range(0, n_loops):
       numpy_array = np.vstack([numpy_array, numpy_row]) # 5.8 micros
    duration = perf_counter() - start_clock
    print('numpy 1.14 takes {:.3f} micros per row'.format(duration * 1e6 / n_loops))

    start_clock = perf_counter()
    for count in range(0, n_loops):
        py_array.append(py_row) # .15 micros
    numpy_array = np.array(py_array) # 43.9 micros       
    duration = perf_counter() - start_clock
    print('python 3.6 takes {:.3f} micros per row'.format(duration * 1e6 / n_loops))
    sleep(15)

#time_it() prints:

numpy 1.14 takes 5.971 micros per row
python 3.6 takes 0.694 micros per row

因此,七年前对原始问题的简单解决方案是在将行转换为numpy数组后,使用vstack()添加新行。但是更现实的解决方案应该考虑在这些情况下vstack的性能不佳。如果您不需要在每次添加后对数组进行数据分析,最好将新行缓冲到python行列表(实际上是列表列表)中,然后将它们作为一个组添加到numpy数组中在进行任何数据分析之前使用vstack()。


5
import numpy as np
array_ = np.array([[1,2,3]])
add_row = np.array([[4,5,6]])

array_ = np.concatenate((array_, add_row), axis=0)

3

如果您可以在一个操作中完成构造,那么类似vstack-with-fancy-indexing的答案就是很好的方法。但是,如果您的情况更加复杂,或者您的行不断增加,那么您可能想要增加数组。实际上,执行类似这样的numpythonic方法-动态增长数组-是动态增长列表:

A = np.array([[1,2,3],[4,5,6]])
Alist = [r for r in A]
for i in range(100):
    newrow = np.arange(3)+i
    if i%5:
        Alist.append(newrow)
A = np.array(Alist)
del Alist

列表针对这种访问模式进行了高度优化。在列表形式时,您没有方便的numpy多维索引,但是只要您要追加,就很难比行数组列表做得更好。


3

我使用更快的“ np.vstack”,例如:

import numpy as np

input_array=np.array([1,2,3])
new_row= np.array([4,5,6])

new_array=np.vstack([input_array, new_row])

2

您可以用来numpy.append()在numpty数组后附加一行,然后再将其整形为矩阵。

import numpy as np
a = np.array([1,2])
a = np.append(a, [3,4])
print a
# [1,2,3,4]
# in your example
A = [1,2]
for row in X:
    A = np.append(A, row)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.