Czytam niektóre automatyczne dane pogodowe z Internetu. Obserwacje odbywają się co 5 minut i są zestawiane w miesięczne pliki dla każdej stacji pogodowej. Po zakończeniu analizowania pliku DataFrame wygląda mniej więcej tak:
Sta Precip1hr Precip5min Temp DewPnt WindSpd WindDir AtmPress
Date
2001-01-01 00:00:00 KPDX 0 0 4 3 0 0 30.31
2001-01-01 00:05:00 KPDX 0 0 4 3 0 0 30.30
2001-01-01 00:10:00 KPDX 0 0 4 3 4 80 30.30
2001-01-01 00:15:00 KPDX 0 0 3 2 5 90 30.30
2001-01-01 00:20:00 KPDX 0 0 3 2 10 110 30.28
Problemem jest to, że czasami naukowiec cofa się i koryguje obserwacje - nie poprzez edycję błędnych wierszy, ale przez dodanie duplikatu wiersza na końcu pliku. Prosty przykład takiego przypadku pokazano poniżej:
import pandas
import datetime
startdate = datetime.datetime(2001, 1, 1, 0, 0)
enddate = datetime.datetime(2001, 1, 1, 5, 0)
index = pandas.DatetimeIndex(start=startdate, end=enddate, freq='H')
data1 = {'A' : range(6), 'B' : range(6)}
data2 = {'A' : [20, -30, 40], 'B' : [-50, 60, -70]}
df1 = pandas.DataFrame(data=data1, index=index)
df2 = pandas.DataFrame(data=data2, index=index[:3])
df3 = df2.append(df1)
df3
A B
2001-01-01 00:00:00 20 -50
2001-01-01 01:00:00 -30 60
2001-01-01 02:00:00 40 -70
2001-01-01 03:00:00 3 3
2001-01-01 04:00:00 4 4
2001-01-01 05:00:00 5 5
2001-01-01 00:00:00 0 0
2001-01-01 01:00:00 1 1
2001-01-01 02:00:00 2 2
A więc muszę df3
równomiernie zostać:
A B
2001-01-01 00:00:00 0 0
2001-01-01 01:00:00 1 1
2001-01-01 02:00:00 2 2
2001-01-01 03:00:00 3 3
2001-01-01 04:00:00 4 4
2001-01-01 05:00:00 5 5
Myślałem, że dodanie kolumny liczb wierszy ( df3['rownum'] = range(df3.shape[0])
) pomogłoby mi wybrać najniższy wiersz dla dowolnej wartości DatetimeIndex
, ale utknąłem przy ustalaniu instrukcji group_by
lub pivot
(lub ???) instrukcji, aby to zadziałało.
Odpowiedzi:
Sugerowałbym użycie zduplikowanej metody na samym indeksie Pandas:
Podczas gdy wszystkie inne metody działają, aktualnie akceptowana odpowiedź jest zdecydowanie najmniej wydajna dla podanego przykładu. Ponadto, chociaż metoda groupby jest tylko nieco mniej wydajna, uważam, że powielona metoda jest bardziej czytelna.
Korzystając z podanych przykładowych danych:
Zauważ, że możesz zachować ostatni element, zmieniając argument keep.
Należy również zauważyć, że ta metoda również działa
MultiIndex
(przy użyciu df1, jak podano w przykładzie Paula ):źródło
loc
może nie być konieczne. Po prostu zróbdf3 = df3[~df3.index.duplicated(keep='first')]
, co spowoduje usunięcie wszystkich wierszy ze zduplikowanym indeksem z wyjątkiem pierwszego wystąpienia.Prostym rozwiązaniem jest użycie
drop_duplicates
Dla mnie działało to szybko na dużych zestawach danych.
Wymaga to, aby „rownum” było kolumną z duplikatami. W zmodyfikowanym przykładzie „rownum” nie ma duplikatów, dlatego nic nie jest eliminowane. Naprawdę chcemy, aby „cols” były ustawione na indeks. Nie znalazłem sposobu, aby powiedzieć drop_duplicates, aby uwzględniało tylko indeks.
Oto rozwiązanie, które dodaje indeks jako kolumnę ramki danych, upuszcza na nim duplikaty, a następnie usuwa nową kolumnę:
A jeśli chcesz odzyskać wszystko w odpowiedniej kolejności, po prostu wywołaj
sort
ramkę danych.źródło
df.reset_index().drop_duplicates(cols='index',take_last=True).set_index('index')
reset_index()
dodaje kolumny poziom_0, poziom_1 itd. A jeśli indeks ma nazwę, nazwa ta zostanie użyta zamiast etykiety „indeks”. To sprawia, że jest to coś więcej niż jedno-liniowy, aby zrobić to dobrze dla dowolnej ramki DataFrame.index_label = getattr(df.index, 'names', getattr(df.index, 'name', 'index'))
wtedycols=index_label
wtedyset_index(index_labels)
i nawet to nie jest niezawodny (nie będzie pracować dla nienazwanych multiindexes).idx = df.index.name or 'index'
, można równieżdf2 = df.reset_index(); df2.drop_duplicates(idx, inplace=True); df2.set_index(idx, inplace=True)
uniknąć pośrednich kopii (z powoduinplace=True
)O mój. To jest naprawdę takie proste!
Kontynuuj edycję 2013-10-29 W przypadku, gdy mam dość skomplikowane
MultiIndex
, myślę, że wolę takiegroupby
podejście. Oto prosty przykład dla potomności:i oto ważna część
źródło
level=[0,1]
, że będzie działać, jeśli istnieją 2 poziomydf1.groupby(level=[0,1]).last()
. To powinno być częścią Pand jakodrop_duplicates
df.index.names
jest tylko łatwym sposobem grupowania według wszystkich poziomów indeksu.xarray
przypadku duplikatów indeksów DateTime, które powodują, że operacjeds.resample
ids.groupby
operacje kończą się niepowodzeniemxarray
tak długo, jak zmienićgrouped = df3.groupby(level=0)
sięgrouped = df3.groupby(dim='time')
albo cokolwiek wymiar jest to, że zawiera duplikatyNiestety nie sądzę, aby Pandy pozwalały na zrzucanie duplikatów z indeksów. Sugerowałbym następujące:
źródło
Jeśli ktoś taki jak ja lubi manipulowanie danymi łańcuchowymi za pomocą notacji kropek pandy (np. Potokowanie), przydatne mogą być następujące:
Umożliwia to tworzenie łańcuchów takich instrukcji:
źródło
TypeError: 'Series' objects are mutable, thus they cannot be hashed
.. Czy to naprawdę działało dla ciebie?Usuń duplikaty (na początku)
Usuń duplikaty (Keep Last Last)
Testy: 10 000 pętli z wykorzystaniem danych OP
źródło