it-swarm.com.de

Pandas berechnen Zeitreihendaten mit mehreren Indizes oder Spalten auf 15 und 45 Minuten neu

Ich habe einige Zeitreihendaten als Pandas-Datenrahmen, der mit Beobachtungen um 15 Minuten nach der vollen Stunde und 45 Minuten nach der vollen Stunde (Zeitintervalle von 30 Minuten) beginnt und dann die Frequenz auf jede Minute ändert. Ich möchte die Daten neu abtasten, damit sie alle 30 Minuten, jeweils um 15 und 45 nach Ablauf der Stunden, für den gesamten Datenrahmen regelmäßig abgerufen werden.

Ich dachte an zwei Möglichkeiten, dies zu erreichen.
1. Filtern Sie einfach den Datenrahmen nach allen Beobachtungen bei 15 Minuten und 45 Minuten, wobei Sie die Zeitreihendaten als Spalte im Datenrahmen verwenden.
2. Stellen Sie den Index so ein, dass die Zeitreihendaten Teil eines Multi-Index sind (die 0. Ebene des Index ist die Wetterstation, die 1. Ebene ist die Zeit der Beobachtung) und verwenden Sie die Pandas-Funktion für Datum-Zeit-Zeitreihen, z als resample().

Der ursprüngliche Datenrahmen (Wetter) sieht folgendermaßen aus:

                  parsed_time           Pressure  Temp    Hum
Station   (index)   
Bow       1        2018-04-15 14:15:00   1012     20.0    87
          2        2018-04-15 14:45:00   1013     20.0    87
          3        2018-04-15 15:15:00   1012     21.0    87
          4        2018-04-15 15:45:00   1014     22.0    86
          5        2018-04-15 16:00:00   1015     22.0    86
          6        2018-04-15 16:01:00   1012     25.0    86
          7        2018-04-15 16:02:00   1012     25.0    86
Stratford 8        2018-04-15 14:15:00   1011     18.0    87
          9        2018-04-15 14:45:00   1011     18.0    87
          10       2018-04-15 15:15:00   1012     18.0    87
          11       2018-04-15 15:45:00   1014     19.0    86
          12       2018-04-15 16:00:00   1014     19.0    86
          13       2018-04-15 16:01:00   1015     19.0    86
          14       2018-04-15 16:02:00   1016     20.0    86
          15       2018-04-15 16:04:00   1016     20.0    86

Bei Methode 1 tritt das Problem auf, dass meine booleschen Auswahloperationen nicht wie erwartet zu funktionieren scheinen. Zum Beispiel

weather_test = weather[weather['parsed_time'].dt.minute == (15 & 45)]

gibt parsed_time-Werte wie folgt aus:

2018-04-15 14:13:00
2018-04-15 15:13:00

weather_test = weather[weather['parsed_time'].dt.minute == (15 | 45)]

ergibt parsed_time Werte wie diesen:

2018-04-15 14:47:00
2018-04-15 14:47:00

Ich kann nichts in den Dokumenten finden, um dieses Verhalten zu erklären. Was ich will, ist Druck, Temperatur, Luftfeuchtigkeit pro Station zu folgenden Zeiten:

2018-04-15 14:45:00    
2018-04-15 15:15:00  
2018-04-15 15:45:00
2018-04-15 16:15:00

und so weiter.

Bei Methode 2 dachte ich daran, die Daten erneut abzutasten, damit Beobachtungen, für die ich Minuten für Minuten Daten habe, durch den Mittelwert der letzten 30 Minuten ersetzt werden. Diese Funktionalität scheint nur zu funktionieren, wenn die Spalte parsed_time Teil des Index ist. Daher habe ich den folgenden Code verwendet, um parsed_time als Teil eines Multi-Index festzulegen:

weather.set_index('parsed_time', append=True, inplace=True)
weather.index.set_names('station', level=0, inplace=True)
weather = weather.reset_index(level=1, drop=True)

so erhalten Sie einen Datenrahmen, der wie folgt aussieht:

                                  Pressure   Temp    Hum
Station    parsed_time
Bow            2018-04-15 14:15:00    1012       20.0    87
           2018-04-15 14:45:00    1013       20.0    87
           2018-04-15 15:15:00    1012       21.0    87
           2018-04-15 15:45:00    1014       22.0    86
           2018-04-15 16:00:00    1015       22.0    86
           2018-04-15 16:01:00    1012       25.0    86
           2018-04-15 16:02:00    1012       25.0    86
Stratford  2018-04-15 14:15:00    1011       18.0    87
           2018-04-15 14:45:00    1011       18.0    87
           2018-04-15 15:15:00    1012       18.0    87
           2018-04-15 15:45:00    1014       19.0    86
           2018-04-15 16:00:00    1014       19.0    86
           2018-04-15 16:01:00    1015       19.0    86
           2018-04-15 16:02:00    1016       20.0    86
           2018-04-15 16:04:00    1016       20.0    86

Beachten Sie, dass die Abtastung von Beobachtungen von 30 Minuten nach 15 und 45 nach 45 nach jeder Minute (z. B.: 01,: 02,: 14 usw.) und auch nach Station variiert - nicht alle Stationen haben jede Beobachtung.

Ich habe es versucht:

weather_test = weather.resample('30min', level=1).mean()

dies wird jedoch ohne Versatz neu abgetastet und die Stationsebene im Multi-Index wird ebenfalls entfernt.

Das gewünschte Ergebnis ist folgendes:

                              Pressure   Temp    Hum
Station    parsed_time
Bow            2018-04-15 14:15:00    1012       20.0    87
           2018-04-15 14:45:00    1013       20.0    87
           2018-04-15 15:15:00    1012       21.0    87
           2018-04-15 15:45:00    1014       22.0    86
           2018-04-15 16:15:00    1013       24.0    86
Stratford  2018-04-15 14:15:00    1011       18.0    87
           2018-04-15 14:45:00    1011       18.0    87
           2018-04-15 15:15:00    1012       18.0    87
           2018-04-15 15:45:00    1014       19.0    86
           2018-04-15 16:15:00    1015       19.5    86

wobei die Beobachtungen von Minute zu Minute als Mittelwert über einen Zeitraum von 30 Minuten um: 15 und: 45 nach der vollen Stunde neu abgetastet wurden.

Es ist wichtig, die Station als Ebene im Multi-Index zu halten. Ich kann den Zeitindex nicht als eigenen Index verwenden, da sich die Werte für jede Station wiederholen (und nicht eindeutig sind).

Wir bedanken uns für jede Hilfe, da ich mit dieser schon eine Weile im Kreis bin. Vielen Dank!

Ich habe mir einige frühere Beiträge angesehen, darunter: Boolescher Filter mit einem Zeitstempelwert für einen Datenrahmen in Python
Wie runde ich die Datums Uhrzeitspalte auf die nächste Viertelstunde - /
und: Neuabtasten eines Pandas-Datenrahmens mit Zeitreihen mit mehreren Indizes was für etwas, das recht einfach sein sollte, etwas kompliziert erscheint ...

und die Dokumente: http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.resample.html Danke!

5
LucieCBurgess

Ausgehend von Ihrem vorletzten Datenrahmen (nach Verwendung von weather.reset_index(Station, inplace=True)):

                           Station  Pressure  Temp   Hum
parsed_time                                         
2018-04-15 14:15:00        Bow    1012.0  20.0  87.0
2018-04-15 14:45:00        Bow    1013.0  20.0  87.0
2018-04-15 15:15:00        Bow    1012.0  21.0  87.0
2018-04-15 15:45:00        Bow    1014.0  22.0  86.0
2018-04-15 16:00:00        Bow    1015.0  22.0  86.0
2018-04-15 16:01:00        Bow    1012.0  25.0  86.0
2018-04-15 16:02:00        Bow    1012.0  25.0  86.0
2018-04-15 14:15:00  Stratford    1011.0  18.0  87.0
2018-04-15 14:45:00  Stratford    1011.0  18.0  87.0
2018-04-15 15:15:00  Stratford    1012.0  18.0  87.0
2018-04-15 15:45:00  Stratford    1014.0  19.0  86.0
2018-04-15 16:00:00  Stratford    1014.0  19.0  86.0
2018-04-15 16:01:00  Stratford    1015.0  19.0  86.0
2018-04-15 16:02:00  Stratford    1016.0  20.0  86.0
2018-04-15 16:04:00  Stratford    1016.0  20.0  86.0

sie können eine Kombination aus groupby und resample verwenden:

res = weather.groupby('Station').resample('30min').mean().reset_index('Station')

Standardmäßig wählt resample die Bin-Intervalle [16:00, 16:30) und [16:30, 17:00). Wie Sie bereits bemerkt haben, wird der Zeitindex ohne Versatz neu abgetastet, aber Sie können ihn später mit DateOffset wieder hinzufügen:

res.index = res.index + pd.DateOffset(minutes=15)

was ergibt:

                           Station  Pressure  Temp   Hum
parsed_time                                         
2018-04-15 14:15:00        Bow   1012.00  20.0  87.0
2018-04-15 14:45:00        Bow   1013.00  20.0  87.0
2018-04-15 15:15:00        Bow   1012.00  21.0  87.0
2018-04-15 15:45:00        Bow   1014.00  22.0  86.0
2018-04-15 16:15:00        Bow   1013.00  24.0  86.0
2018-04-15 14:15:00  Stratford   1011.00  18.0  87.0
2018-04-15 14:45:00  Stratford   1011.00  18.0  87.0
2018-04-15 15:15:00  Stratford   1012.00  18.0  87.0
2018-04-15 15:45:00  Stratford   1014.00  19.0  86.0
2018-04-15 16:15:00  Stratford   1015.25  19.5  86.0

Alternativ können Sie den Offset auch direkt in der resample-Methode angeben:

weather.groupby('Station').resample('30min', loffset=pd.Timedelta('15min')).mean()
1
chuni0r

Ich habe Ihre Daten nicht, daher kann ich dies nicht direkt untersuchen, aber versuchen Sie die folgende Syntax für die Option, die Sie als Option 1 bezeichnen:

weather_test = weather[(weather['parsed_time'].dt.minute == 15) | (weather['parsed_time'].dt.minute == 45)]
1
BossaNova

Wenn Sie ohne Index beginnen (mit Ausnahme eines Zeilenindex), können Sie Folgendes ausführen:

# Create a rounded timestamp
df['parsed_time_rounded'] = (df['parsed_time'] - pd.Timedelta('15min')).dt.round('30min') + pd.Timedelta('15min')
# Group by the station, and the rounded timestamp instead of the raw timestamp
df.groupby(['Station', 'parsed_time_rounded']).mean()
1
PMende