質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

Q&A

解決済

3回答

961閲覧

DataFrame.resample() で範囲外のデータを参照した集計をしたい

foy

総合スコア12

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

0グッド

0クリップ

投稿2020/02/28 07:08

python3系、pandasでデータ処理をしています。

  • dfのindexはdatetime64で1時間ごとのデータがある。
  • 1日毎に集計値を計算したい。
  • その計算には、その日のデータだけではなく、前後のデータが必要。
  • データのある期間はもちろん有限ですが、途中の欠損値はありません。

集計方法の例は下記です。
例1) k=0,1,...,23で、k時とk+1時の差を2乗して合計を集計値とする。(つまり、翌日の0時を含む25時間分のデータが必要)
例2) その日を含む前3日間の平均を、集計値とする。(resampleと移動平均を同時にやる感じ)

などです。

データは例えばですが、下記のような形式です。

python

1import pandas as pd 2import numpy as np 3 4periods = 73 5 6np.random.seed(42) 7df = pd.DataFrame( 8 np.random.rand(periods), 9 columns=['data'], 10 index=pd.date_range('2020-01-01 00:00', periods=periods, freq='H'), 11 ) 12 13
data
2020-01-01 00:000.374540
2020-01-01 01:000.950714
2020-01-01 02:000.731994
2020-01-01 03:000.598658
2020-01-01 04:000.156019
......
2020-01-03 20:000.074551
2020-01-03 21:000.986887
2020-01-03 22:000.772245
2020-01-03 23:000.198716
2020-01-04 00:000.005522

やりたいことはDataFrame.resample()でできることに近いのですが、範囲外のデータを使うという意味でやり方がわかりません。rollingだと重すぎるし、日毎にリサンプルしたいので、ちょっと違う気がしています。
それなりに大きなデータを多数処理しなくてはならないため、処理時間も気になっており、無理ならデータ列をndarrayにしてから計算しようかとかも考えています。

どなたかいい案があれば、ご教示いただけますよう、よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

数値データであり、処理時間を気にするならnumpyを使うべきです。
欠損値がないということから、常に0時からの一時間刻みのデータであるとしてコードを記載します。

python

1import pandas as pd 2import numpy as np 3 4periods = 73 5 6np.random.seed(42) 7df = pd.DataFrame( 8 np.random.rand(periods), 9 columns=['data'], 10 index=pd.date_range('2020-01-01 00:00', periods=periods, freq='H'), 11 ) 12 13arr = df['data'].to_numpy()

このとき、

例1

python

1size = arr.size//24*24 2result = (np.diff(arr) ** 2)[:size].reshape(-1, 24).sum(1) 3# array([3.57046265, 4.84927938, 4.81231076])

次との差を計算し、24個ずつにまとめてから合計します。

例2

python

1t = 3 # 3日間 2strides = arr.strides[0] 3window_arr = np.lib.stride_tricks.as_strided( 4 arr, (arr.size//24-t+1, t*24), (strides*24, strides), writeable=False) 5# [arr[0:72], arr[24:96], ..., arr[-72:]]という配列に等しい 6 7result = np.r_[[np.nan]*(t-1), window_arr.mean(1)] 8# array([ nan, nan, 0.46798213])

スライドウィンドウを使って3日分ずつの配列を作成し、平均します。
過去3日分が見れていない1日目と2日目の分、nanを付け足してます。

投稿2020/02/28 14:19

kirara0048

総合スコア1399

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

foy

2020/03/02 00:21

詳しい回答ありがとうございます。 参考にさせていただきます。
foy

2020/03/02 01:36

numpyはあまり使ったことがなかったので、大変勉強になりました。 本当にありがとうございます。m(_ _)m
guest

0

処理時間はわかりませんが

k=0,1,...,23で、k時とk+1時の差を2乗して合計を集計値

まず差を計算してから、日付でグルーピングして集計するとどうでしょうか。

python

1 2import pandas as pd 3import numpy as np 4 5periods = 73 6 7np.random.seed(42) 8df = pd.DataFrame( 9 np.random.rand(periods), 10 columns=['data'], 11 index=pd.date_range('2020-01-01 00:00', periods=periods, freq='H'), 12 ) 13 14dd = df.diff() 15dg = dd.groupby(pd.Grouper(freq='d')) 16r = dg.apply(lambda x: np.sum(x**2)) 17print(r)

投稿2020/02/28 09:04

t_obara

総合スコア5488

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

foy

2020/03/02 01:37

pd.Grouperの使い方がよくわかっていなかったので大変参考になります。 ありがとうございました。
guest

0

diff()は知りませんでした。
ありがとうございます。参考にさせていただきます。

投稿2020/03/02 00:05

foy

総合スコア12

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問