Insira uma linha no dataframe do pandas

112

Eu tenho um dataframe:

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]

e preciso adicionar uma primeira linha [2, 3, 4] para obter:

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

Tentei o append()e concat()funções, mas não consigo encontrar a maneira certa de como fazer isso.

Como adicionar / inserir séries no dataframe?

Meloun
fonte
6
observe que é melhor usar, s1.valuesem vez de list(s1)criar uma lista totalmente nova usando list(s1).
acushner de
7
Não entendo por que todo mundo ama tanto os pandas quando algo que deveria ser tão simples é tão chato e lento.
MattCochrane

Respostas:

145

Basta atribuir uma linha a um índice específico, 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

E você obtém, conforme desejado:

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

Veja na documentação do Pandas Indexação: Configuração com ampliação .

Piotr Migdal
fonte
2
Se você não quiser definir com ampliação, mas inserir dentro do dataframe, dê uma olhada em stackoverflow.com/questions/15888648/…
FooBar
6
alternativa de índice de deslocamento: df.sort (). reset_index (drop = True)
Meloun
2
df.sort está obsoleto, use df.sort_index ()
GBGOLC de
1
@Piotr - funciona muito bem, mas o que acontece quando você deseja duplicar uma linha de seu quadro de dados, como df.loc[-1] = df.iloc[[0]], e inseri-la? O quadro vem com uma coluna de índice adicionada com erro ValueError: cannot set a row with mismatched columns (consulte stackoverflow.com/questions/47340571/… )
Growler
5
Eu acho que df.loc[-1] = [2, 3, 4] # adding a rowé um pouco enganador, já que -1não é a última linha / elemento, como é para arrays Python.
flow2k
26

Não tenho certeza de como você estava chamando, concat()mas deve funcionar, desde que ambos os objetos sejam do mesmo tipo. Talvez o problema seja que você precisa lançar seu segundo vetor para um dataframe? Usar o df que você definiu funciona para mim:

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

Uma maneira de conseguir isso é

>>> 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

Geralmente, é mais fácil anexar dataframes, não séries. No seu caso, como você deseja que a nova linha esteja "no topo" (com id inicial) e não haja nenhuma função pd.prepend(), primeiro crio o novo dataframe e, em seguida, acrescento o antigo.

ignore_indexirá ignorar o índice antigo em andamento em seu dataframe e garantir que a primeira linha realmente comece com índice em 1vez de reiniciar com índice 0.

Isenção de responsabilidade típica: Cetero censeo ... anexar linhas é uma operação bastante ineficiente. Se você se preocupa com o desempenho e pode, de alguma forma, garantir primeiro a criação de um dataframe com o índice correto (mais longo) e, em seguida, apenas inserir a linha adicional no dataframe, você definitivamente deve fazer isso. Vejo:

>>> 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)]

Até agora, temos o que você tinha como df:

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

Mas agora você pode inserir facilmente a linha da seguinte maneira. Como o espaço foi pré-alocado, isso é mais 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
fonte
Essa é uma boa solução alternativa. Eu estava tentando inserir séries no dataframe. É bom o suficiente para mim no momento.
Meloun de
Eu gosto mais da última opção. Isso realmente corresponde ao que eu realmente quero fazer. Obrigado @FooBar!
Jade Cacho
13

Eu criei uma função curta que permite um pouco mais de flexibilidade ao inserir uma linha:

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 poderia ser ainda mais abreviado para:

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

Então você pode usar algo como:

df = insert_row(2, df, df_new)

onde 2é a posição do índice dfonde você deseja inserir df_new.

elPastor
fonte
7

Podemos usar numpy.insert. Isso tem a vantagem de flexibilidade. Você só precisa especificar o índice no qual deseja inserir.

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

Pois np.insert(df.values, 0, values=[2, 3, 4], axis=0), 0 indica à função o local / índice em que você deseja colocar os novos valores.

Tai
fonte
6

isso pode parecer muito simples, mas é incrível que uma função simples de inserir nova linha não esteja embutida. Eu li muito sobre anexar um novo df ao original, mas estou me perguntando se isso seria mais rápido.

df.loc[0] = [row1data, blah...]
i = len(df) + 1
df.loc[i] = [row2data, blah...]
Aaron Melgar
fonte
Você quis dizer "acrescentando um novo df" ou apenas "acrescentando uma nova linha", como mostra seu código?
smci
desculpe, minha frase não foi clara. Já li outras soluções de pessoas que concatam / acrescentam um novo dataframe com apenas uma única linha. mas na minha solução é apenas uma única linha no dataframe existente, sem a necessidade de um dataframe adicional ser criado
Aaron Melgar
6

Abaixo está a melhor maneira de inserir uma linha no dataframe do pandas sem classificar e redefinir um í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
fonte
por que você diria que esta é a melhor maneira?
Yuca
então seria bom fornecer evidências para apoiar essa afirmação, você cronometrou?
Yuca de
1
você pode usar pd.isna para evitar a importação de numpy
kato2
2

É muito simples adicionar uma linha em um pandas DataFrame:

  1. Crie um dicionário Python regular com os mesmos nomes de colunas que o seu Dataframe;

  2. Use o pandas.append()método e passe o nome do seu dicionário, onde .append()é um método nas instâncias do DataFrame;

  3. Adicione ignore_index=Truelogo após o nome do dicionário.

Pepe
fonte
Esta é provavelmente a opção mais preferível (por volta de 2020).
David Golembiowski
1

concat()parece ser um pouco mais rápido do que a inserção e reindexação da última linha. Caso alguém se pergunte sobre a velocidade das duas principais abordagens:

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 loop (média ± desvio padrão de 7 execuções, 1 loop cada)

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 loop (média ± desvio padrão de 7 execuções, 1 loop cada)

M. Viaz
fonte
0

Você pode simplesmente anexar a linha ao final do DataFrame e, em seguida, ajustar o índice.

Por exemplo:

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()

Ou use concatcomo:

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

A maneira mais simples de adicionar uma linha em um quadro de dados do pandas é:

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

Exemplo:

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

NB: o comprimento da sua lista deve corresponder ao do quadro de dados.

Pepe
fonte
fez o truque para mim!
Sam Shaw