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

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

新規登録して質問してみよう
ただいま回答率
85.35%
データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

pandas

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

Q&A

解決済

3回答

1124閲覧

pandas 標準偏差を日毎に求める

mn.py

総合スコア41

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

pandas

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

0グッド

0クリップ

投稿2021/10/18 13:20

data

下記のようなdataframeがあります。
(実際のデータは数千万行のデータになります)
範囲指定で

日付時間price
2020-11-019:0010
2020-11-0110:0020
2020-11-0111:0030
2020-11-0112:0040
2020-11-0113:0050
2020-11-029:00100
2020-11-0210:00200
2020-11-0211:00300
2020-11-0212:00400
2020-11-0213:00500
2020-11-039:00110
2020-11-0310:00120
2020-11-0311:00130
2020-11-0312:00140
2020-11-0313:00150

やりたいこと

日毎に前日までのpriceの標準偏差を算出したい。

欲しい結果

日付標準偏差
2020-11-0215.8113883
2020-11-03177.40412

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

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

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

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

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

guest

回答3

0

集合を結合したときの分散は、もとの集合の要素数、平均、分散がわかっていれば計算しなおせます。
(combine stdevとかで検索してみてください)

なので、日付でgroupbyして、要素数、平均、分散を計算しておけば、それらから複数日に対しての分散が計算できます。

下記では、式を変形して累計和(cumsum)で、前日までの標準偏差を計算するようにしてみました。

python

1import pandas as pd 2import numpy as np 3 4df = ... 5 6df2 = df.groupby('日付')['price'].agg(['count', 'mean', 'var']) 7n = df2['count'] 8m = df2['mean'] 9v = df2['var'] 10 11N = n.cumsum().shift() 12M = (n * m).cumsum().shift() / N 13V = v * (n - 1) + (np.square(m - M) / (1 / N + 1 / n)).fillna(0.0) 14V = V.cumsum().shift() / (N - 1) 15 16stdev = np.sqrt(V).rename('標準偏差').to_frame() 17print(stdev) 18# 標準偏差 19#日付 20#2020-11-01 NaN 21#2020-11-02 15.811388 22#2020-11-03 177.404121

数千万行のデータで動くかは未検証です。

投稿2021/10/19 11:55

bsdfan

総合スコア4794

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

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

0

質問のようなケースなら逐次的に計算するとよいでしょう。
参考:分散の逐次更新

具体的にはwelfordを使うと以下のように計算でき
日付の切り替わり毎にそれまでの値を出力すればよいです。

Python

1 2import pandas as pd 3from io import StringIO 4import math 5import numpy as np 6from welford import Welford 7 8s = """日付,時間,price 92020-11-01,9:00,10 102020-11-01,10:00,20 112020-11-01,11:00,30 122020-11-01,12:00,40 132020-11-01,13:00,50 142020-11-02,9:00,100 152020-11-02,10:00,200 162020-11-02,11:00,300 172020-11-02,12:00,400 182020-11-02,13:00,500 192020-11-03,9:00,110 202020-11-03,10:00,120 212020-11-03,11:00,130 222020-11-03,12:00,140 232020-11-03,13:00,150""" 24df = pd.read_csv(StringIO(s)) 25df['date'] = pd.to_datetime( df['日付'] + ' ' + df['時間']) 26df = df.loc[:,['date','price']] 27 28row = [] 29w = Welford() 30for v in df['price']: 31 w.add(np.array(v)) 32 row.append([w.mean, math.sqrt(w.var_s)]) 33 34row = np.array(row) 35df['mean'] = row[:,0] 36df['std'] = row[:,1] 37print(df) 38""" 39 date price mean std 400 2020-11-01 09:00:00 10 153.333333 NaN 411 2020-11-01 10:00:00 20 153.333333 7.071068 422 2020-11-01 11:00:00 30 153.333333 10.000000 433 2020-11-01 12:00:00 40 153.333333 12.909944 444 2020-11-01 13:00:00 50 153.333333 15.811388 455 2020-11-02 09:00:00 100 153.333333 31.885211 466 2020-11-02 10:00:00 200 153.333333 66.547513 477 2020-11-02 11:00:00 300 153.333333 103.639140 488 2020-11-02 12:00:00 400 153.333333 140.781549 499 2020-11-02 13:00:00 500 153.333333 177.404121 5010 2020-11-03 09:00:00 110 153.333333 169.115345 5111 2020-11-03 10:00:00 120 153.333333 161.658075 5212 2020-11-03 11:00:00 130 153.333333 154.952433 5313 2020-11-03 12:00:00 140 153.333333 148.924717 5414 2020-11-03 13:00:00 150 153.333333 143.510411 55""" 56 57print(df['price'].describe()) 58""" 59count 15.000000 60mean 153.333333 61std 143.510411 62min 10.000000 6325% 45.000000 6450% 120.000000 6575% 175.000000 66max 500.000000 67Name: price, dtype: float64 68"""

投稿2021/10/19 04:33

can110

総合スコア38341

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

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

mn.py

2021/10/19 15:07

Welfordというのを初めて知りました!ありがとうございました!!やってみます!
guest

0

ベストアンサー

以下です。

python

1>>> print(df) 2 日付 時間 price 30 2020-11-01 9:00 10 41 2020-11-01 10:00 20 52 2020-11-01 11:00 30 63 2020-11-01 12:00 40 74 2020-11-01 13:00 50 85 2020-11-02 9:00 100 96 2020-11-02 10:00 200 107 2020-11-02 11:00 300 118 2020-11-02 12:00 400 129 2020-11-02 13:00 500 1310 2020-11-03 9:00 110 1411 2020-11-03 10:00 120 1512 2020-11-03 11:00 130 1613 2020-11-03 12:00 140 1714 2020-11-03 13:00 150 18>>> print(df.groupby('日付')[['price']].std().rename(columns={'price':'標準偏差'}).reset_index()) 19 日付 標準偏差 200 2020-11-01 15.811388 211 2020-11-02 158.113883 222 2020-11-03 15.811388

投稿2021/10/18 14:15

ppaul

総合スコア24670

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

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

mn.py

2021/10/18 14:41

ありがとうございました。 日毎ではなく、前日までの全てのpriceの標準偏差を求めたかったのです。 質問の題名が悪かったです。ごめんなさい。
mn.py

2021/10/19 15:08

そうですよね、、処理の速度も並列化して短縮しないとだめですよね、、、ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問