web-dev-qa-db-ja.com

Pandas時系列データを15分と45分にリサンプリング-マルチインデックスまたは列を使用

私はいくつかの時系列データをa Pandasデータフレームとして1時間15分と45分(30分間隔の時間間隔)の観測で開始し、頻度を1分ごとに変更します。データを再サンプリングして、データフレーム全体に対して、過去15時間と45時間で、30分ごとの定期的な頻度になるようにします。

これを達成するための2つの方法を考えました。
1。時系列データをデータフレームの列として使用して、15分と45分ですべての観測のデータフレームをフィルターするだけです。
2。時系列データがマルチインデックスの一部になるようにインデックスを再設定し(インデックスの0番目のレベルは気象台で、1番目のレベルは観測の時間です)、Pandas resample()などの日時timeseries機能。

元のデータフレームである天気は次のようになります。

                  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

方法1では、ブール選択操作が期待どおりに動作しないように見えるという問題があります。例えば

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

次のようなparsed_time値を提供します:

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

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

結果は次のようなparsed_time値になります:

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

ドキュメントでこの動作を説明するものは見つかりません。私が欲しいのは、次の時間におけるステーション別の圧力、温度、湿度です。

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

等々。

方法2では、分単位のデータがある観測値が直前の30分の平均値に置き換えられるように、データをリサンプリングすることを考えました。この機能は、parsed_time列がインデックスの一部である場合にのみ機能するようです。そのため、次のコードを使用して、parsed_timeをマルチインデックスの一部として設定しました。

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)

最終的には次のようなデータフレームになります。

                                  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

観測値のサンプリングは、過去15時と45時の30分ごとから毎分まで変化します(例:01、:02、:14など)。また、測点によっても異なります。すべての測点にすべての観測があるわけではありません。

私はこれを試しました:

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

しかし、これはオフセットなしでリサンプリングし、マルチインデックスの測点レベルも取り除きます。

望ましい結果はこれです:

                              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

1分ごとの観測値が、毎時15分と45分の30分間隔の平均としてリサンプリングされています。

ステーションをマルチインデックスのレベルとして維持することは不可欠です。値は各ステーションで繰り返されるため(それは一意ではないため)、時間インデックスをそれ自体のインデックスとして使用することはできません。

しばらくの間、私はこれを一周しているので、すべての助けに感謝します。ありがとう!

私はこれまでにかなりの数の以前の投稿を見てきました: Pythonのデータフレームのタイムスタンプ値を使用したブールフィルター
日時列を最も近い15分に丸める方法
and: リサンプリングa pandasマルチインデックスを含むtimeseriesを含むデータフレーム これは、かなり単純なものに対して少し複雑に思われます...

とドキュメント: http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.resample.html ありがとうございます!

7
LucieCBurgess

2番目の最後のデータフレームから開始します(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

groupbyresampleの組み合わせを使用できます:

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

デフォルトでは、resampleはビンの間隔を選択します[16:00, 16:30)および[16:30, 17:00)。既にお気づきのとおり、時間インデックスはオフセットなしでリサンプリングされますが、後でDateOffsetを使用して追加できます。

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

これにより、

                           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

または、resampleメソッドで直接オフセットを指定することもできます。

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

私はあなたのデータを持っていないのでこれを直接調べることはできませんが、オプション1として参照するオプションに対して次の構文を試してください。

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

インデックスなしで開始する場合(行インデックスを除く)、以下を実行できます。

# 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