Numpy - agrega fila a la matriz

161

¿Cómo se agregan filas a una matriz numpy?

Tengo una matriz A:

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

Deseo agregar filas a esta matriz desde otra matriz X si el primer elemento de cada fila en X cumple una condición específica.

Las matrices de Numpy no tienen un método 'agregar' como el de las listas, o eso parece.

Si A y X fueran listas, simplemente haría:

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

¿Hay una forma numpythonic de hacer el equivalente?

Gracias S ;-)

Darren J. Fitzpatrick
fuente
Ver también stackoverflow.com/questions/8486294/…
Thomas Ahle

Respuestas:

120

¿Qué es X? Si es una matriz 2D, ¿cómo puede comparar su fila con un número i < 3:?

EDITAR después del comentario de OP:

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

agregar a Atodas las filas desde Xdonde el primer 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
fuente
1
Lo siento, buen punto! Suponga una matriz 2D de la cual el primer elemento de cada fila debe cumplir una condición. Lo editaré. Gracias, S ;-)
Darren J. Fitzpatrick
2
@ DarrenJ.Fitzpatrick Tenga en cuenta que al hacer este tipo de manipulación usted trabaja en contra del buen trabajo que hace Numpy en la asignación previa de memoria para su matriz existente A. Claramente para problemas pequeños como en esta respuesta, esto no es un problema, pero puede ser más problemático para datos grandes.
dtlussier
166

bueno, puedes hacer esto:

  newrow = [1,2,3]
  A = numpy.vstack([A, newrow])
jknair
fuente
2
@Kris ¿Por qué está en desuso? No veo nada en los documentos
Georgy
1
@ Georgia Para ser honesto, no lo sé. Estaba buscando respuestas iguales a las tuyas :-). No puedo recordar ahora por qué escribí el comentario anterior. Debo haber visto en los documentos que está en desuso. Pero mirando los documentos ahora ... no lo dice. ¿Es posible que lo desaprobaron, luego cambiaron de opinión y decidieron que sería demasiado molesto para muchas personas desaprobarlo y eliminarlo?
Kris
32

Como esta pregunta se hizo 7 años antes, en la última versión que estoy usando es la versión numpy 1.13, y python3, estoy haciendo lo mismo agregando una fila a una matriz, recuerde poner un paréntesis doble en el segundo argumento, de lo contrario, aumentará el error de dimensión.

Aquí estoy agregando en la matriz A

1 2 3
4 5 6

con una fila

7 8 9

mismo uso en 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]]]

Solo para interesar a alguien, si desea agregar una columna,

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

siguiendo lo que hicimos antes en la matriz A, agregando una columna

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

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

Si no es necesario realizar cálculos después de cada fila, es mucho más rápido agregar filas en Python y luego convertirlas en numpy. Aquí hay pruebas de tiempo que usan python 3.6 vs. numpy 1.14, agregando 100 filas, una a la 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

Entonces, la solución simple a la pregunta original, de hace siete años, es usar vstack () para agregar una nueva fila después de convertir la fila en una matriz numpy. Pero una solución más realista debería considerar el bajo rendimiento de vstack en esas circunstancias. Si no necesita ejecutar el análisis de datos en la matriz después de cada adición, es mejor almacenar las nuevas filas en una lista de filas de Python (una lista de listas, realmente) y agregarlas como un grupo a la matriz numpy usando vstack () antes de hacer cualquier análisis de datos.

rbasham
fuente
10

También puedes hacer esto:

newrow = [1,2,3]
A = numpy.concatenate((A,newrow))
leva
fuente
2
hmmm cuando probé esto, simplemente se agregó al final de A, en lugar de agregar una nueva fila como lo solicitó OP.
Todd Curry
13
probablementenp.concatenate((A,newrow), axis=0)
Konstantinos Roditakis
3
A partir de la versión numpy 1.12.1(y en Python 3), parece que se intenta concatenar un vector a una matriz ValueError: all the input arrays must have same number of dimensions. Parece que quiere que el vector se reforme explícitamente en un vector de columna o fila antes de que esté dispuesto a concatenarlo.
MRule
3
@MRule puede solucionarlo usando corchetes dobles según la respuesta de @Flora PJ Li stackoverflow.com/a/47845065/1410035 . newrow = [[1,2,3]]
Tom Saleeba
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
fuente
3

Si puede hacer la construcción en una sola operación, entonces algo como la respuesta vstack-with-fancy-indexing es un buen enfoque. Pero si su condición es más complicada o sus filas aparecen sobre la marcha, es posible que desee aumentar la matriz. De hecho, la forma numpythonic de hacer algo como esto - crecer dinámicamente una matriz - es hacer crecer dinámicamente una 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

Las listas están altamente optimizadas para este tipo de patrón de acceso; no tiene una indexación multidimensional numpy conveniente mientras está en forma de lista, pero mientras agregue es difícil hacerlo mejor que una lista de matrices de filas.

usuario2475529
fuente
3

Yo uso 'np.vstack' que es más 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
fuente
2

Puede usar numpy.append()para agregar una fila a una matriz numpty y volver a dar forma a una matriz más adelante.

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
fuente