J'ai des données de série temporelle sous la forme d'un Pandas dataframe qui commence par des observations à 15 minutes après l'heure et 45 minutes après (intervalles de 30 minutes), puis change de fréquence à chaque minute. Je veux rééchantillonner les données de manière à ce qu'elles aient une fréquence régulière toutes les 30 minutes, à 15 heures et 45 heures pour l'ensemble de la trame de données.
J'ai pensé à deux façons d'y parvenir.
1. Il suffit de filtrer la trame de données pour toutes les observations à 15 min et 45 min, en utilisant les données de série chronologique sous forme de colonne dans la trame de données.
2. Réinitialisez l'index pour que les données de série chronologique fassent partie d'un multi-index (le 0ème niveau de l'index est la station météo, le 1er niveau est l'heure de l'observation) et utilisez le Pandas fonctionnalité de série temporelle date-heure telle que resample()
.
La trame de données d'origine, la météo, ressemble à ceci:
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
Avec la méthode 1, j'ai le problème que mes opérations de sélection booléenne ne semblent pas fonctionner comme prévu. Par exemple
weather_test = weather[weather['parsed_time'].dt.minute == (15 & 45)]
donne des valeurs parsed_time comme ceci:
2018-04-15 14:13:00
2018-04-15 15:13:00
weather_test = weather[weather['parsed_time'].dt.minute == (15 | 45)]
entraîne des valeurs parsed_time comme ceci:
2018-04-15 14:47:00
2018-04-15 14:47:00
Je ne trouve rien dans les documents pour expliquer ce comportement. Ce que je veux, c'est la pression, la température, l'humidité par station aux heures suivantes:
2018-04-15 14:45:00
2018-04-15 15:15:00
2018-04-15 15:45:00
2018-04-15 16:15:00
etc.
Avec la méthode 2, j'ai pensé à rééchantillonner les données afin que les observations pour lesquelles j'ai des données minute par minute soient remplacées par la moyenne des 30 minutes précédentes. Cette fonctionnalité ne semble fonctionner que si la colonne parsed_time fait partie de l'index, j'ai donc utilisé le code suivant pour définir parsed_time dans le cadre d'un multi-index:
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)
pour finir avec une trame de données qui ressemble à ceci:
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
Notez que l'échantillonnage des observations varie de toutes les 30 minutes à: 15 passé et: 45 passé à chaque minute (par exemple: 01,: 02,: 14, etc.), et il varie également selon la station - toutes les stations n'ont pas toutes les observations.
J'ai essayé ceci:
weather_test = weather.resample('30min', level=1).mean()
mais cela rééchantillonne sans décalage et supprime également le niveau de la station dans le multi-index.
Le résultat souhaité est le suivant:
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
où les observations minute par minute ont été rééchantillonnées comme la moyenne sur un intervalle de 30 minutes à: 15 et: 45 après l'heure.
Garder la station comme niveau dans le multi-index est essentiel. Je ne peux pas utiliser l'index de temps comme un index à lui seul car les valeurs se répètent pour chaque station (et ne sont pas uniques).
Toute l'aide a été appréciée car je tourne en rond avec celui-ci depuis un moment maintenant. Merci!
J'ai regardé pas mal de messages précédents, notamment: filtre booléen utilisant une valeur d'horodatage sur une trame de données en Python
Comment arrondir la colonne datetime au quart d'heure le plus proche
et: Rééchantillonnage d'un pandas dataframe avec multi-index contenant des séries temporelles ce qui semble un peu compliqué pour quelque chose qui devrait être assez simple ...
et les documents: http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.resample.html Merci!
À partir de votre avant-dernière trame de données (après avoir utilisé 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
vous pouvez utiliser une combinaison de groupby
et resample
:
res = weather.groupby('Station').resample('30min').mean().reset_index('Station')
Par défaut, resample
choisit les intervalles de bac [16:00, 16:30)
et [16:30, 17:00)
. Comme vous l'avez déjà remarqué, l'index de temps est rééchantillonné sans décalage, mais vous pouvez l'ajouter par la suite en utilisant DateOffset
:
res.index = res.index + pd.DateOffset(minutes=15)
ce qui donne:
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
Vous pouvez également spécifier le décalage directement dans la méthode de rééchantillonnage:
weather.groupby('Station').resample('30min', loffset=pd.Timedelta('15min')).mean()
Je n'ai pas vos données, je ne peux donc pas l'examiner directement, mais essayez la syntaxe suivante pour l'option que vous appelez l'option 1:
weather_test = weather[(weather['parsed_time'].dt.minute == 15) | (weather['parsed_time'].dt.minute == 45)]
Si vous commencez sans index (sauf pour un index de ligne), vous pouvez effectuer les opérations suivantes:
# 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()