Pandas de Python: llenar un marco de datos fila por fila

133

La simple tarea de agregar una fila a un pandas.DataFrameobjeto parece ser difícil de lograr. Hay 3 preguntas de stackoverflow relacionadas con esto, ninguna de las cuales da una respuesta funcional.

Esto es lo que estoy tratando de hacer. Tengo un DataFrame del que ya conozco la forma, así como los nombres de las filas y columnas.

>>> df = pandas.DataFrame(columns=['a','b','c','d'], index=['x','y','z'])
>>> df
     a    b    c    d
x  NaN  NaN  NaN  NaN
y  NaN  NaN  NaN  NaN
z  NaN  NaN  NaN  NaN

Ahora, tengo una función para calcular los valores de las filas de forma iterativa. ¿Cómo puedo completar una de las filas con un diccionario o un pandas.Series? Aquí hay varios intentos que han fallado:

>>> y = {'a':1, 'b':5, 'c':2, 'd':3} 
>>> df['y'] = y
AssertionError: Length of values does not match length of index

Aparentemente trató de agregar una columna en lugar de una fila.

>>> y = {'a':1, 'b':5, 'c':2, 'd':3} 
>>> df.join(y)
AttributeError: 'builtin_function_or_method' object has no attribute 'is_unique'

Mensaje de error muy poco informativo.

>>> y = {'a':1, 'b':5, 'c':2, 'd':3} 
>>> df.set_value(index='y', value=y)
TypeError: set_value() takes exactly 4 arguments (3 given)

Aparentemente eso es solo para establecer valores individuales en el marco de datos.

>>> y = {'a':1, 'b':5, 'c':2, 'd':3} 
>>> df.append(y)
Exception: Can only append a Series if ignore_index=True

Bueno, no quiero ignorar el índice, de lo contrario aquí está el resultado:

>>> df.append(y, ignore_index=True)
     a    b    c    d
0  NaN  NaN  NaN  NaN
1  NaN  NaN  NaN  NaN
2  NaN  NaN  NaN  NaN
3    1    5    2    3

Alineó los nombres de las columnas con los valores, pero perdió las etiquetas de las filas.

>>> y = {'a':1, 'b':5, 'c':2, 'd':3} 
>>> df.ix['y'] = y
>>> df
                                  a                                 b  \
x                               NaN                               NaN
y  {'a': 1, 'c': 2, 'b': 5, 'd': 3}  {'a': 1, 'c': 2, 'b': 5, 'd': 3}
z                               NaN                               NaN

                                  c                                 d
x                               NaN                               NaN
y  {'a': 1, 'c': 2, 'b': 5, 'd': 3}  {'a': 1, 'c': 2, 'b': 5, 'd': 3}
z                               NaN                               NaN

Eso también falló miserablemente.

Entonces, cómo lo haces ?

xApple
fuente

Respuestas:

92

df['y'] establecerá una columna

ya que desea establecer una fila, use .loc

Tenga en cuenta que .ixaquí es equivalente, el suyo falló porque trató de asignar un diccionario a cada elemento de la fila, yprobablemente no lo que desea; la conversión a una serie le dice a los pandas que desea alinear la entrada (por ejemplo, no tiene que especificar todos los elementos)

In [7]: df = pandas.DataFrame(columns=['a','b','c','d'], index=['x','y','z'])

In [8]: df.loc['y'] = pandas.Series({'a':1, 'b':5, 'c':2, 'd':3})

In [9]: df
Out[9]: 
     a    b    c    d
x  NaN  NaN  NaN  NaN
y    1    5    2    3
z  NaN  NaN  NaN  NaN
Jeff
fuente
Veo. Entonces, el locatributo del marco de datos define un especial __setitem__que hace la magia, supongo.
xApple
¿Puedes construir esto en una pasada (es decir, con columnas, índice e y)?
Andy Hayden
55
Entonces, si puedo generar una fila a la vez, ¿cómo construiría el marco de datos de manera óptima?
xApple
¿Esperaba alguna variante de df = pd.DataFrame({'y': pd.Series(y)}, columns=['a','b','c','d'], index=['x','y','z'])trabajo?
Andy Hayden
Prob @xApple es mejor para que construyas una lista de dictados (o lista), luego solo pases al constructor, será mucho más eficiente
Jeff
71

Mi enfoque fue, pero no puedo garantizar que esta sea la solución más rápida.

df = pd.DataFrame(columns=["firstname", "lastname"])
df = df.append({
     "firstname": "John",
     "lastname":  "Johny"
      }, ignore_index=True)
fluir
fuente
44
Esto funcionó de manera brillante para mí y me gusta el hecho de que explícitamente appendlos datos en el marco de datos.
Jonny Brooks el
1
Tenga en cuenta que esta respuesta necesita que cada fila incluya el nombre de la columna. Lo mismo para la respuesta aceptada.
pashute
Esto también funciona si no conoce el número de filas por adelantado.
irene
34

Esta es una versión más simple.

import pandas as pd
df = pd.DataFrame(columns=('col1', 'col2', 'col3'))
for i in range(5):
   df.loc[i] = ['<some value for first>','<some value for second>','<some value for third>']`
Satheesh
fuente
44
solo quiero preguntar, ¿es eficiente esta CPU y memoria?
czxttkl
1
¿Cómo sé la última fila de df para que anexe a la última fila cada vez?
pashute
25

Si sus filas de entrada son listas en lugar de diccionarios, la siguiente es una solución simple:

import pandas as pd
list_of_lists = []
list_of_lists.append([1,2,3])
list_of_lists.append([4,5,6])

pd.DataFrame(list_of_lists, columns=['A', 'B', 'C'])
#    A  B  C
# 0  1  2  3
# 1  4  5  6
stackoverflowuser2010
fuente
pero ¿qué hago si tengo un índice múltiple? df1 = pd.DataFrame (list_of_lists, columnas ['A', 'B', 'C'], index = ['A', 'B']) no funciona. Forma incorrecta ¿Así que cómo?
pashute