Insertar una fila en el marco de datos de pandas

112

Tengo un marco de datos:

s1 = pd.Series([5, 6, 7])
s2 = pd.Series([7, 8, 9])

df = pd.DataFrame([list(s1), list(s2)],  columns =  ["A", "B", "C"])

   A  B  C
0  5  6  7
1  7  8  9

[2 rows x 3 columns]

y necesito agregar una primera fila [2, 3, 4] para obtener:

   A  B  C
0  2  3  4
1  5  6  7
2  7  8  9

He probado append()y concat()funciona pero no puedo encontrar la manera correcta de hacerlo.

¿Cómo agregar / insertar series en el marco de datos?

Meloun
fuente
6
tenga en cuenta que es mejor usar s1.valuesen lugar de, list(s1)ya que creará una lista completamente nueva usando list(s1).
Acushner
7
No entiendo por qué todo el mundo ama tanto a los pandas cuando algo que debería ser tan simple es tan doloroso y tan lento.
MattCochrane

Respuestas:

145

Simplemente asigne una fila a un índice en particular, usando loc:

 df.loc[-1] = [2, 3, 4]  # adding a row
 df.index = df.index + 1  # shifting index
 df = df.sort_index()  # sorting by index

Y obtienes, como desees:

    A  B  C
 0  2  3  4
 1  5  6  7
 2  7  8  9

Consulte en la documentación de Pandas Indexación: Configuración con ampliación .

Piotr Migdal
fuente
2
Si no desea configurar con ampliación, pero insertar dentro del marco de datos, eche un vistazo a stackoverflow.com/questions/15888648/…
FooBar
6
Alternativa de índice de cambio: df.sort (). reset_index (drop = True)
Meloun
2
df.sort está en desuso, use df.sort_index ()
GBGOLC
1
@Piotr: esto funciona muy bien, pero ¿qué sucede cuando desea duplicar una fila de su marco de datos, como df.loc[-1] = df.iloc[[0]], e insertarla? El marco viene con una columna de índice agregada que da error ValueError: cannot set a row with mismatched columns (ver stackoverflow.com/questions/47340571/… )
Growler
5
Creo que df.loc[-1] = [2, 3, 4] # adding a rowes un poco engañoso, ya -1que no es la última fila / elemento, como lo es para las matrices de Python.
flow2k
26

No estoy seguro de cómo estaba llamando, concat()pero debería funcionar siempre que ambos objetos sean del mismo tipo. ¿Quizás el problema es que necesita convertir su segundo vector en un marco de datos? Usando el df que definiste, lo siguiente funciona para mí:

df2 = pd.DataFrame([[2,3,4]], columns=['A','B','C'])
pd.concat([df2, df])
mgilbert
fuente
Mejor respuesta ^ :)
Cam.Davidson.Pilon
23

Una forma de lograr esto es

>>> pd.DataFrame(np.array([[2, 3, 4]]), columns=['A', 'B', 'C']).append(df, ignore_index=True)
Out[330]: 
   A  B  C
0  2  3  4
1  5  6  7
2  7  8  9

Generalmente, es más fácil agregar marcos de datos, no series. En su caso, dado que desea que la nueva fila esté "en la parte superior" (con la identificación inicial), y no hay ninguna función pd.prepend(), primero creo el nuevo marco de datos y luego agrego el anterior.

ignore_indexignorará el antiguo índice en curso en su marco de datos y se asegurará de que la primera fila realmente comience con index en 1lugar de reiniciar con index 0.

Descargo de responsabilidad típico: Cetero censeo ... agregar filas es una operación bastante ineficiente. Si le preocupa el rendimiento y de alguna manera puede asegurarse de crear primero un marco de datos con el índice correcto (más largo) y luego simplemente insertar la fila adicional en el marco de datos, definitivamente debería hacerlo. Ver:

>>> index = np.array([0, 1, 2])
>>> df2 = pd.DataFrame(columns=['A', 'B', 'C'], index=index)
>>> df2.loc[0:1] = [list(s1), list(s2)]
>>> df2
Out[336]: 
     A    B    C
0    5    6    7
1    7    8    9
2  NaN  NaN  NaN
>>> df2 = pd.DataFrame(columns=['A', 'B', 'C'], index=index)
>>> df2.loc[1:] = [list(s1), list(s2)]

Hasta ahora, tenemos lo que tenías como df:

>>> df2
Out[339]: 
     A    B    C
0  NaN  NaN  NaN
1    5    6    7
2    7    8    9

Pero ahora puede insertar fácilmente la fila de la siguiente manera. Dado que el espacio fue preasignado, esto es más eficiente.

>>> df2.loc[0] = np.array([2, 3, 4])
>>> df2
Out[341]: 
   A  B  C
0  2  3  4
1  5  6  7
2  7  8  9
FooBar
fuente
Esa es una buena solución alternativa, estaba tratando de insertar series en el marco de datos. Es lo suficientemente bueno para mí en este momento.
Meloun
Me gusta más la última opción. Esto realmente coincide con lo que realmente quiero hacer. ¡Gracias @FooBar!
Jade Cacho
13

Reuní una función corta que permite un poco más de flexibilidad al insertar una fila:

def insert_row(idx, df, df_insert):
    dfA = df.iloc[:idx, ]
    dfB = df.iloc[idx:, ]

    df = dfA.append(df_insert).append(dfB).reset_index(drop = True)

    return df

que podría reducirse aún más a:

def insert_row(idx, df, df_insert):
    return df.iloc[:idx, ].append(df_insert).append(df.iloc[idx:, ]).reset_index(drop = True)

Entonces podrías usar algo como:

df = insert_row(2, df, df_new)

donde 2está la posición del índice en dfdonde desea insertar df_new.

elPastor
fuente
7

Podemos usar numpy.insert. Esto tiene la ventaja de la flexibilidad. Solo necesita especificar el índice en el que desea insertar.

s1 = pd.Series([5, 6, 7])
s2 = pd.Series([7, 8, 9])

df = pd.DataFrame([list(s1), list(s2)],  columns =  ["A", "B", "C"])

pd.DataFrame(np.insert(df.values, 0, values=[2, 3, 4], axis=0))

    0   1   2
0   2   3   4
1   5   6   7
2   7   8   9

Porque np.insert(df.values, 0, values=[2, 3, 4], axis=0), 0 le dice a la función el lugar / índice en el que desea colocar los nuevos valores.

Tai
fuente
6

esto puede parecer demasiado simple, pero es increíble que no esté incorporada una función simple para insertar una nueva fila. He leído mucho sobre agregar un nuevo df al original, pero me pregunto si esto sería más rápido.

df.loc[0] = [row1data, blah...]
i = len(df) + 1
df.loc[i] = [row2data, blah...]
Aaron Melgar
fuente
¿Quiso decir "agregar un nuevo df" o simplemente "agregar una nueva fila", como muestra su código?
smci
lo siento, mi oración no fue clara. He leído soluciones de otras personas que concatenan / añaden un marco de datos completamente nuevo con una sola fila. pero en mi solución es solo una fila en el marco de datos existente sin necesidad de crear un marco de datos adicional
Aaron Melgar
6

A continuación, se muestra la mejor manera de insertar una fila en el marco de datos de pandas sin ordenar y restablecer un índice:

import pandas as pd

df = pd.DataFrame(columns=['a','b','c'])

def insert(df, row):
    insert_loc = df.index.max()

    if pd.isna(insert_loc):
        df.loc[0] = row
    else:
        df.loc[insert_loc + 1] = row

insert(df,[2,3,4])
insert(df,[8,9,0])
print(df)
Sagar Rathod
fuente
¿Por qué dirías que esta es la mejor manera?
Yuca
entonces sería bueno proporcionar evidencia para respaldar esa afirmación, ¿lo cronometró?
Yuca
1
puede usar pd.isna para evitar importar numpy
kato2
2

Es bastante simple agregar una fila a un pandas DataFrame:

  1. Cree un diccionario Python normal con los mismos nombres de columnas que su Dataframe;

  2. Use el pandas.append()método y pase el nombre de su diccionario, donde .append()es un método en las instancias de DataFrame;

  3. Agregue ignore_index=Truejusto después del nombre de su diccionario.

Pepe
fuente
Esta es probablemente la opción más preferible (alrededor de 2020).
David Golembiowski
1

concat()parece ser un poco más rápido que la inserción y reindexación de la última fila. En caso de que alguien se pregunte acerca de la velocidad de dos enfoques superiores:

In [x]: %%timeit
     ...: df = pd.DataFrame(columns=['a','b'])
     ...: for i in range(10000):
     ...:     df.loc[-1] = [1,2]
     ...:     df.index = df.index + 1
     ...:     df = df.sort_index()

17,1 s ± 705 ms por bucle (media ± desviación estándar de 7 corridas, 1 bucle cada una)

In [y]: %%timeit
     ...: df = pd.DataFrame(columns=['a', 'b'])
     ...: for i in range(10000):
     ...:     df = pd.concat([pd.DataFrame([[1,2]], columns=df.columns), df])

6,53 s ± 127 ms por bucle (media ± desviación estándar de 7 corridas, 1 bucle cada una)

M. Viaz
fuente
0

Simplemente puede agregar la fila al final del DataFrame y luego ajustar el índice.

Por ejemplo:

df = df.append(pd.DataFrame([[2,3,4]],columns=df.columns),ignore_index=True)
df.index = (df.index + 1) % len(df)
df = df.sort_index()

O utilizar concatcomo:

df = pd.concat([pd.DataFrame([[1,2,3,4,5,6]],columns=df.columns),df],ignore_index=True)
Xinyi Li
fuente
-1

La forma más sencilla de agregar una fila en un marco de datos de pandas es:

DataFrame.loc[ location of insertion ]= list( )

Ejemplo:

DF.loc[ 9 ] = [ ´Pepe , 33, ´Japan ]

NB: la longitud de su lista debe coincidir con la del marco de datos.

Pepe
fuente
me hizo el truco!
Sam Shaw