2016-11-09 8 views
5

Załóżmy, że mam dwie dataframes:pandy: Usuń wszystkie wiersze w obrębie przedziału czasu indeksie czasu kolejnej serii (tj wykluczania zakres czasowy)

#df1 
time 
2016-09-12 13:00:00.017 1.0 
2016-09-12 13:00:03.233 1.0 
2016-09-12 13:00:10.256 1.0 
2016-09-12 13:00:19.605 1.0 

#df2 
time 
2016-09-12 13:00:00.017 1.0 
2016-09-12 13:00:00.233 0.0 
2016-09-12 13:00:01.016 1.0 
2016-09-12 13:00:01.505 0.0 
2016-09-12 13:00:06.017 1.0 
2016-09-12 13:00:07.233 0.0 
2016-09-12 13:00:08.256 1.0 
2016-09-12 13:00:19.705 0.0 

Chcę usunąć wszystkie wiersze w df2 które są do +1 sekundę indeksów czasowych w df1, więc otrzymując:

#result 
time 
2016-09-12 13:00:01.505 0.0 
2016-09-12 13:00:06.017 1.0 
2016-09-12 13:00:07.233 0.0 
2016-09-12 13:00:08.256 1.0 

Jaki jest najbardziej skuteczny sposób to zrobić? Nie widzę niczego przydatnego do wykluczania zakresu czasu w interfejsie API.

Odpowiedz

11

Można użyć pd.merge_asof który jest nowym włączenie zaczynając 0.19.0 a także przyjmuje argument tolerancja dopasować +/- że określoną ilość przedziale czasowym.

# Assuming time to be set as the index axis for both df's 
df1.reset_index(inplace=True) 
df2.reset_index(inplace=True) 

df2.loc[pd.merge_asof(df2, df1, on='time', tolerance=pd.Timedelta('1s')).isnull().any(1)] 

enter image description here

Zauważ, że domyślne dopasowanie odbywa się w wstecznej kierunku, co oznacza, że ​​wybór następuje w ostatnim rzędzie w prawym DataFrame (df1), którego "on" klucz (co jest "time") jest mniejszy lub równy lewemu (df2). Dlatego parametr tolerance rozciąga się tylko w tym kierunku (zacofany), co daje zakres dopasowywania tolerance.

Aby mieć zarówno naprzód jak tyłu wyszukiwań możliwe, zaczynając 0.20.0 ten można osiągnąć poprzez wykorzystanie direction='nearest' argument i włączenia go do wywołania funkcji. Z tego powodu interfejs tolerance jest rozszerzany w obie strony, co daje pasujący zakres pasma .

+1

pokonać mnie do niego ... – piRSquared

+2

haha ​​... Pamiętam o komentarzu @ MaxU kilka dni temu o jego tolerancji. –

1

Jednym ze sposobów, aby to zrobić byłoby odnośnika poprzez indeksowanie czasu (zakładając, że zarówno czas Kolumny są indeksy):

td = pd.to_timedelta(1, unit='s') 
df2.apply(lambda row: df1[row.name - td:row.name].size > 0, axis=1) 
4

podobny pomysł jak @Nickil Maveli, ale przy użyciu reindex zbudować logiczną podziałowe:

df2 = df2[df1.reindex(df2.index, method='nearest', tolerance=pd.Timedelta('1s')).isnull()] 

Wynikiem:

time 
2016-09-12 13:00:01.505 0.0 
2016-09-12 13:00:06.017 1.0 
2016-09-12 13:00:07.233 0.0 
2016-09-12 13:00:08.256 1.0 
Powiązane problemy