Como adicionar uma nova linha a uma matriz numpy vazia


158

Usando matrizes Python padrão, posso fazer o seguinte:

arr = []
arr.append([1,2,3])
arr.append([4,5,6])
# arr is now [[1,2,3],[4,5,6]]

No entanto, não posso fazer a mesma coisa numpy. Por exemplo:

arr = np.array([])
arr = np.append(arr, np.array([1,2,3]))
arr = np.append(arr, np.array([4,5,6]))
# arr is now [1,2,3,4,5,6]

Também examinei vstack, mas quando uso vstackem uma matriz vazia, recebo:

ValueError: all the input array dimensions except for the concatenation axis must match exactly

Então, como anexo uma nova linha a uma matriz vazia em numpy?


1
Se estiver vazio, por que se preocupar? Basta iniciar a partir de uma matriz contendo apenas a primeira linha.
jonrsharpe

10
Eu só quero saber se é possível anexar a uma matriz numpy vazia. Às vezes, é mais fácil escrever código assim, pois as operações de acréscimo estão em loop.
Tony Stark

5
Dada a forma como matrizes numpy trabalho, você é muito melhor construir um array vazio, em seguida, colocar os dados em, por exemplo, See stackoverflow.com/questions/568962/...
jonrsharpe

Respostas:


227

A maneira de "iniciar" a matriz que você deseja é:

arr = np.empty((0,3), int)

Que é uma matriz vazia, mas tem a dimensionalidade adequada.

>>> arr
array([], shape=(0, 3), dtype=int64)

Não se esqueça de anexar ao longo do eixo 0:

arr = np.append(arr, np.array([[1,2,3]]), axis=0)
arr = np.append(arr, np.array([[4,5,6]]), axis=0)

Mas, @jonrsharpe está certo. De fato, se você for anexar um loop, seria muito mais rápido anexar a uma lista como no seu primeiro exemplo, depois converter para uma matriz numpy no final, já que você realmente não está usando numpy como pretendido durante o loop:

In [210]: %%timeit
   .....: l = []
   .....: for i in xrange(1000):
   .....:     l.append([3*i+1,3*i+2,3*i+3])
   .....: l = np.asarray(l)
   .....: 
1000 loops, best of 3: 1.18 ms per loop

In [211]: %%timeit
   .....: a = np.empty((0,3), int)
   .....: for i in xrange(1000):
   .....:     a = np.append(a, 3*i+np.array([[1,2,3]]), 0)
   .....: 
100 loops, best of 3: 18.5 ms per loop

In [214]: np.allclose(a, l)
Out[214]: True

A maneira numpythonic de fazer isso depende da sua aplicação, mas seria mais como:

In [220]: timeit n = np.arange(1,3001).reshape(1000,3)
100000 loops, best of 3: 5.93 µs per loop

In [221]: np.allclose(a, n)
Out[221]: True

e se eu tiver que fazer isso 10 ^ 5 ou 10 ^ 6 vezes? parece que nenhum desses métodos será válido. alguma sugestão?
Rho Phi

@ Roberto, geralmente há alguma maneira de determinar o tamanho ou a forma (no mínimo, os valores seriam preferíveis) da matriz com antecedência. Você acha que pode fazer isso? Anexar deve realmente ser uma operação de uma ou duas vezes.
askewchan

às vezes você não consegue adivinhar as dimensões, é a vida. No entanto, você pode alocar uma matriz grande o suficiente e atribuir valores às suas visualizações. Eu não gosto disso, porque existem valores indesejados que é preciso encontrar uma maneira de "mascarar". Essa idéia de mascarar realmente não se encaixa no meu gosto.
Rho Phi

Não há necessidade de mascarar, apenas cortar! a = a[:N] Embora eu acredite firmemente que você deve encontrar uma maneira de vetorizá-la (poste uma nova pergunta com suas especificações, se precisar de ajuda) ou apenas use listas até que o ciclo termine.
askewchan

29

Aqui está a minha solução:

arr = []
arr.append([1,2,3])
arr.append([4,5,6])
np_arr = np.array(arr)

A matriz resultante tem um tipo de objeto, o que não é aceitável em certos casos
zer0fool

26

Nesse caso, você pode querer usar as funções np.hstack e np.vstack

arr = np.array([])
arr = np.hstack((arr, np.array([1,2,3])))
# arr is now [1,2,3]

arr = np.vstack((arr, np.array([4,5,6])))
# arr is now [[1,2,3],[4,5,6]]

Você também pode usar a função np.concatenate.

Felicidades


7
Não funcionará se a segunda matriz tiver dimensão> = 2 como as ((2, 2)). Parece-me que não há como evitar casos de fronteira se você estiver criando matrizes vazias por concatenação.
Taozi 20/10/2015

Não é uma boa solução, pois é necessário verificar a dimensão todas as vezes.
SKR

1

usando uma definição de dtype personalizada, o que funcionou para mim foi:

import numpy

# define custom dtype
type1 = numpy.dtype([('freq', numpy.float64, 1), ('amplitude', numpy.float64, 1)])
# declare empty array, zero rows but one column
arr = numpy.empty([0,1],dtype=type1)
# store row data, maybe inside a loop
row = numpy.array([(0.0001, 0.002)], dtype=type1)
# append row to the main array
arr = numpy.row_stack((arr, row))
# print values stored in the row 0
print float(arr[0]['freq'])
print float(arr[0]['amplitude'])

1

No caso de adicionar novas linhas para a matriz em loop, atribua a matriz diretamente para a primeira vez em loop, em vez de inicializar uma matriz vazia.

for i in range(0,len(0,100)):
    SOMECALCULATEDARRAY = .......
    if(i==0):
        finalArrayCollection = SOMECALCULATEDARRAY
    else:
        finalArrayCollection = np.vstack(finalArrayCollection,SOMECALCULATEDARRAY)

Isso é útil principalmente quando a forma da matriz é desconhecida


0

Eu quero fazer um loop for, mas com o método askewchan ele não funciona bem, então eu o modifiquei.

x=np.empty((0,3))
y=np.array([1 2 3])
for i in ...
x = vstack((x,y))
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.