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?

Tony Stark
fonte
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
askewchan
fonte
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)
just4fun
fonte
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

mrcl
fonte
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'])
boclodoa
fonte
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

Rajesh_Saladi
fonte
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))
Qingdong Wang
fonte