Wstaw wiersz do pandy dataframe


112

Mam ramkę danych:

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]

i muszę dodać pierwszy wiersz [2, 3, 4], aby uzyskać:

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

Próbowałem append()i concat()funkcjonuję, ale nie mogę znaleźć właściwego sposobu, jak to zrobić.

Jak dodać / wstawić serię do Dataframe?


6
zwróć uwagę, że lepiej jest używać s1.valuesw przeciwieństwie do list(s1)tworzenia zupełnie nowej listy przy użyciu list(s1).
acushner

7
Nie rozumiem, dlaczego wszyscy tak bardzo kochają pandy, podczas gdy coś, co powinno być tak proste, jest tak upierdliwe i powolne.
MattCochrane

Odpowiedzi:


145

Po prostu przypisz wiersz do określonego indeksu, używając loc:

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

I otrzymujesz, zgodnie z życzeniem:

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

Zobacz w dokumentacji Pandas Indeksowanie: Ustawienie z powiększeniem .


2
Jeśli nie chcesz ustawiać z powiększeniem, ale wstawić do ramki danych, spójrz na stackoverflow.com/questions/15888648/ ...
FooBar

6
alternatywna zmiana indeksu: df.sort (). reset_index (drop = True)
Meloun

2
df.sort jest przestarzały, użyj df.sort_index ()
GBGOLC

1
@Piotr - to działa świetnie, ale co się dzieje, gdy chcesz zduplikować wiersz z ramki danych, na przykład df.loc[-1] = df.iloc[[0]], i wstawić to? Ramka zawiera dodaną kolumnę indeksu, która powoduje błąd ValueError: cannot set a row with mismatched columns (patrz stackoverflow.com/questions/47340571/ ... )
Growler

5
Myślę, że df.loc[-1] = [2, 3, 4] # adding a rowjest to trochę mylące, ponieważ -1nie jest ostatnim wierszem / elementem, jak to ma miejsce w przypadku tablic Pythona.
flow2k

26

Nie jestem pewien, jak dzwoniłeś, concat()ale powinno działać, o ile oba obiekty są tego samego typu. Może problem polega na tym, że musisz rzucić drugi wektor do ramki danych? Użycie df, które zdefiniowałeś, działa dla mnie:

df2 = pd.DataFrame([[2,3,4]], columns=['A','B','C'])
pd.concat([df2, df])

Najlepsza odpowiedź ^ :)
Cam.Davidson.Pilon

23

Jednym ze sposobów osiągnięcia tego jest

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

Generalnie najłatwiej jest dołączać ramki danych, a nie serie. W twoim przypadku, ponieważ chcesz, aby nowy wiersz był „na wierzchu” (z początkowym identyfikatorem) i nie ma funkcji pd.prepend(), najpierw tworzę nową ramkę danych, a następnie dołączam starą.

ignore_indexzignoruje stary, trwający indeks w ramce danych i zapewni, że pierwszy wiersz faktycznie zaczyna się od indeksu 1zamiast ponownego uruchamiania z indeksem 0.

Typowe zastrzeżenie: Cetero censeo ... dołączanie wierszy jest dość nieefektywną operacją. Jeśli zależy Ci na wydajności, a może w jakiś sposób zapewnić, aby najpierw utworzyć dataframe z prawidłowym wskaźnikiem (dłuższy) a potem po prostu wstawiając dodatkowy wiersz do dataframe, powinno się to zrobić. Widzieć:

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

Jak dotąd mamy to, co miałeś jako df:

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

Ale teraz możesz łatwo wstawić wiersz w następujący sposób. Jest to bardziej wydajne, ponieważ miejsce zostało wstępnie przydzielone.

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

To fajne rozwiązanie do obejścia, próbowałem wstawić serie do ramki danych. W tej chwili to mi wystarcza.
Meloun

Najbardziej podoba mi się ostatnia opcja. To naprawdę pasuje do tego, co naprawdę chcę robić. Dziękuję @FooBar!
Jade Cacho

13

Złożyłem krótką funkcję, która pozwala na nieco większą elastyczność podczas wstawiania wiersza:

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

który można dalej skrócić do:

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

Wtedy możesz użyć czegoś takiego:

df = insert_row(2, df, df_new)

gdzie 2jest pozycja indeksu, w dfktórej chcesz wstawić df_new.


7

Możemy użyć numpy.insert. Ma to zaletę w postaci elastyczności. Musisz tylko określić indeks, do którego chcesz wstawić.

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

Dla np.insert(df.values, 0, values=[2, 3, 4], axis=0), 0 informuje funkcję o miejscu / indeksie, w którym chcesz umieścić nowe wartości.


6

to może wydawać się zbyt proste, ale to niesamowite, że prosta funkcja wstawiania nowego wiersza nie jest wbudowana. Wiele czytałem o dołączaniu nowego pliku df do oryginału, ale zastanawiam się, czy byłoby to szybsze.

df.loc[0] = [row1data, blah...]
i = len(df) + 1
df.loc[i] = [row2data, blah...]

Czy chodziło Ci o „dołączanie nowego df” czy po prostu „dołączanie nowego wiersza”, jak pokazuje Twój kod?
smci

przepraszam, moje zdanie nie było jasne. Czytałem rozwiązania innych osób, które łączą / dołączają zupełnie nową ramkę danych z tylko jednym wierszem. ale w moim rozwiązaniu jest to tylko jeden wiersz w istniejącej ramce danych, nie ma potrzeby tworzenia dodatkowej ramki danych
Aaron Melgar

6

Poniżej byłby najlepszy sposób na wstawienie wiersza do ramki danych pandy bez sortowania i resetowania indeksu:

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)

dlaczego powiedziałbyś, że to najlepszy sposób?
Yuca,

wtedy byłoby miło przedstawić dowody na poparcie tego twierdzenia, czy ustaliliście czas?
Yuca

1
możesz użyć pd.isna, aby uniknąć importowania numpy
kato2

2

Dodanie wiersza do pandy jest całkiem proste DataFrame:

  1. Utwórz zwykły słownik Pythona z takimi samymi nazwami kolumn jak Twój Dataframe;

  2. Użyj pandas.append()metody i przekaż nazwę swojego słownika, gdzie .append()jest metodą w instancjach DataFrame;

  3. Dodaj ignore_index=Truezaraz po nazwie słownika.


Jest to prawdopodobnie najkorzystniejsza opcja (około 2020 r.).
David Golembiowski

1

concat()wydaje się być nieco szybszy niż wstawianie i ponowne indeksowanie ostatniego wiersza. Gdyby ktoś zastanawiał się nad szybkością dwóch najpopularniejszych podejść:

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 na pętlę (średnia ± odchylenie standardowe 7 przebiegów, 1 pętla każdy)

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 na pętlę (średnia ± odchylenie standardowe 7 przebiegów, 1 pętla każdy)


0

Możesz po prostu dołączyć wiersz na końcu ramki DataFrame, a następnie dostosować indeks.

Na przykład:

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

Lub użyj concatjako:

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

-1

Najprostszym sposobem dodania wiersza w ramce danych pandy jest:

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

Przykład:

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

Uwaga: długość twojej listy powinna odpowiadać długości ramki danych.


załatwił mi sprawę!
Sam Shaw
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.