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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

pandas

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

Q&A

解決済

1回答

10860閲覧

時間ごとに単純移動平均を計算する:Pandas

pepasuke623

総合スコア55

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

pandas

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

0グッド

2クリップ

投稿2017/04/19 12:58

###前提・実現したいこと
お世話になります。時間ごとに区切って単純移動平均を出したいと思っています。

例えばこんなデータがあるとします。

//data.csv time,val 10:00:00.111,65 10:00:00.555,68 10:00:00.888,37 10:00:01.111,34 10:00:01.222,36 10:00:01.333,34 10:00:01.555,12 10:00:01.888,64 10:00:02.111,94 10:00:02.555,54 10:00:02.888,47 10:00:03.111,35 10:00:03.555,48 10:00:03.888,43 ・ ・

一秒ごとに取れる値の数がまちまちで,10:00:00台では3個、10:00:01台では5個だったりします。
この中で3秒ごとに取れたデータを平均して1.5秒づつずらして単純移動平均計算したいと思っています。
例えば

  • 10:00:03.000では10:00:00.000から10:00:03.000の間に取れた値を平均して10:00:03.000の横に出力する
  • 10:00:04.500では10:00:01.500から10:00:04.500の間に取れた値を平均して10:00:04.500の横に出力する
  • 10:00:06.000では10:00:03.000から10:00:06.000の間に取れた値を平均して10:00:06.000の横に出力する

という計算を繰り返します。アウトプットイメージとしてはこんな感じでしょうか。

//Output.csv(aveの値は適当に入れた) time,ave 10:00:00,000,Nan 10:00:01.500,Nan 10:00:03.000,37 10:00:04.500,34 10:00:06.000,64 ・ ・ ・

###試したこと
先程調べた限りでは、rollingを使えばのようなものは出来るみたいです。

python

1import pandas as pd 2 3my_parser = lambda date: pd.datetime.strptime('%h:%m:%s.%f') 4 5# ファイルを読み込む 6df = pd.read_csv('data.csv', date_parser=my_parser) 7 8df_new = df.rolling(window=3, min_periods=3).mean()

rollingの場合は移動平均に必要な個数が決まっています。今回行いたいのは時間ごとに枠をずらして,任意の枠に取得できた個数分を平均したいです。

お手数ですが、方法を教えていただければと思います。

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

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

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

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

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

guest

回答1

0

ベストアンサー

こんな感じでよろしいでしょうか?

もう少しスマートに書ける気がしますが、とりあえず。

data.csv

time,val 10:00:00.111,65 10:00:00.555,68 10:00:00.888,37 10:00:01.111,34 10:00:01.222,36 10:00:01.333,34 10:00:01.555,12 10:00:01.888,64 10:00:02.111,94 10:00:02.555,54 10:00:02.888,47 10:00:03.111,35 10:00:03.555,48 10:00:03.888,43

sample.py

Python

1import pandas as pd 2# Data読み込み 3my_parser = lambda time: pd.datetime.strptime('2017-04-01 {}'.format(time), '%Y-%m-%d %H:%M:%S.%f') 4df = pd.read_csv('data.csv', date_parser=my_parser, parse_dates=['time']) 5# DataTimeIndexを生成 6index = pd.date_range('2017-04-01 10:00:00', '2017-04-01 10:00:30', freq='1500ms') 7# 平均を求める際の時間範囲 8range = pd.DateOffset(seconds=3) 9# 移動平均を計算 10result = pd.DataFrame([df[(df['time'] >= d) & (df['time'] <= d+range)]['val'].mean() for d in index], index=index, columns=['MovingAverage']) 11print(result)

やっていることは、コードを見ていただけると解ると思いますが、

  1. まず、10:00:00から10:00:30まで1.5秒Stepの DateTimeIndex を生成
  2. DateTimeIndex の各行毎に各データが時間範囲内かどうかを求める
  3. DateTimeIndex の各行毎に時間範囲内のデータの平均値を算出
  4. DateTimeIndexと平均値データによりDataFrameを構築

となっております。

なお、本来は時刻情報だけ結果を算出したほうがよさそうですが、
時間範囲かどうかを求める条件文を簡略化する都合上、適当な
年月日(2017/04/01)を使用してDateTime情報を生成しております。

投稿2017/04/20 00:50

magichan

総合スコア15898

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

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

pepasuke623

2017/04/22 13:24

ありがとうございます! まず時間ごとの枠を作ってから,その後移動平均(区間ごとに平均の計算をする)ということですね. たしかにこの通りプログラムを作成したら出来ました! どうもありがとうございます!!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問