Numpy - adicionar linha à matriz

161

Como se adiciona linhas a uma matriz numpy?

Eu tenho uma matriz A:

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

Desejo adicionar linhas a esta matriz de outra matriz X se o primeiro elemento de cada linha em X atender a uma condição específica.

As matrizes numpy não têm um método 'anexar' como o das listas, ou assim parece.

Se A e X fossem listas, eu simplesmente faria:

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

Existe uma maneira numpythonic de fazer o equivalente?

Obrigado, S ;-)

Darren J. Fitzpatrick
fonte
Veja também stackoverflow.com/questions/8486294/…
Thomas Ahle 14/14

Respostas:

120

O que é X? Se for um array 2D, como você pode comparar sua linha com um número i < 3:?

EDITAR após o comentário do OP:

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

adicione a Atodas as linhas de Xonde o primeiro elemento < 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]])
eumiro
fonte
1
Desculpe bom ponto! Suponha uma matriz 2D da qual o primeiro elemento de cada linha deve atender a uma condição. Eu vou editar isso. Obrigado, S ;-)
Darren J. Fitzpatrick
2
@ DarrenJ.Fitzpatrick Lembre-se de que, ao fazer esse tipo de manipulação, você trabalha contra o bom trabalho que o Numpy faz na pré-alocação de memória para sua matriz existente A. Claramente, para pequenos problemas, como nesta resposta, isso não é um problema, mas pode ser mais preocupante para grandes dados.
dtlussier
166

bem, você pode fazer isso:

  newrow = [1,2,3]
  A = numpy.vstack([A, newrow])
jknair
fonte
2
@Kris Por que está obsoleto? Não vejo nada no docs
Georgy
1
@ Georgy Para ser sincero, não sei. Eu estava aqui procurando respostas iguais às suas :-). Não me lembro agora por que escrevi o comentário acima. Devo ter visto nos documentos seu uso obsoleto. Mas, olhando os documentos agora ... não é o que diz. É possível que eles tenham desaprovado isso, depois mudaram de idéia novamente e decidiram que seria muito chato para muitas pessoas desaprová-lo e removê-lo?
Kris
32

Como essa pergunta foi feita 7 anos antes, na versão mais recente que eu estou usando é a versão numpy 1.13, e python3, estou fazendo a mesma coisa ao adicionar uma linha a uma matriz, lembre-se de colocar um colchete duplo no segundo argumento, caso contrário, aumentará o erro de dimensão.

Aqui eu estou adicionando na matriz A

1 2 3
4 5 6

com uma linha

7 8 9

mesmo uso em 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]]]

Apenas para alguém interessado, se você quiser adicionar uma coluna,

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

seguindo o que fizemos antes na matriz A, adicionando uma coluna a ela

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

>> array([[1, 2, 3, 2],
          [4, 5, 6, 8]])
Flora PJ Li
fonte
10

Você também pode fazer isso:

newrow = [1,2,3]
A = numpy.concatenate((A,newrow))
cam
fonte
2
hmmm. quando tentei isso, ele foi adicionado ao final de A, em vez de adicionar uma nova linha conforme o pedido do OP.
21813 Todd Curry
13
provavelmentenp.concatenate((A,newrow), axis=0)
Konstantinos Roditakis
3
A partir da versão numpy 1.12.1(e no Python 3), parece que tentar concatenar um vetor para uma matriz aumenta ValueError: all the input arrays must have same number of dimensions. Parece que ele deseja que o vetor seja remodelado explicitamente em um vetor de coluna ou linha antes de estar disposto a concatená-lo.
MRule
3
@MRule, você pode corrigir isso usando colchetes duplos, conforme a resposta de @Flora PJ Li stackoverflow.com/a/47845065/1410035 . newrow = [[1,2,3]]
precisa saber é o seguinte
10

Se nenhum cálculo for necessário após cada linha, é muito mais rápido adicionar linhas no python e converter para numpy. Aqui estão os testes de temporização usando python 3.6 vs. numpy 1.14, adicionando 100 linhas, uma de cada vez:

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

Portanto, a solução simples para a pergunta original, de sete anos atrás, é usar vstack () para adicionar uma nova linha após converter a linha em uma matriz numpy. Mas uma solução mais realista deve considerar o fraco desempenho do vstack nessas circunstâncias. Se você não precisar executar a análise de dados na matriz após cada adição, é melhor armazenar em buffer as novas linhas em uma lista de linhas python (uma lista de listas, na verdade) e adicioná-las como um grupo à matriz numpy usando vstack () antes de fazer qualquer análise de dados.

rbasham
fonte
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)
naman1994
fonte
3

Se você pode fazer a construção em uma única operação, algo como a resposta de indexação vstack-fancy-fancy é uma abordagem adequada. Mas se sua condição for mais complicada ou suas linhas surgirem rapidamente, convém aumentar a matriz. De fato, a maneira numptitônica de fazer algo assim - aumentar dinamicamente uma matriz - é aumentar dinamicamente uma lista:

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

As listas são altamente otimizadas para esse tipo de padrão de acesso; você não tem uma indexação multidimensional numpy conveniente enquanto estiver em forma de lista, mas enquanto estiver anexando, é difícil fazer melhor do que uma lista de matrizes de linha.

user2475529
fonte
3

Eu uso 'np.vstack', que é mais rápido, EX:

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])
RAno
fonte
2

Você pode usar numpy.append()para anexar uma linha à matriz numpty e remodelar para uma matriz posteriormente.

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)
Charles Chow
fonte