よちよちpython

独習 python/Qpython/Pydroid3/termux/Linux

【Pandas】移動平均の出し方

今回は、Pandasで移動平均というものを出す方法。簡単です。



株価や新型コロナPCR検査数のグラフのように、日によって激しく上下するグラフをデータそのままで描くと、トレンドとして上がり調子なのか下がり調子なのか分かりにくくなる。そのため縦軸の値を移動平均というものにして上下のバラツキの少ないグラフにしてあったりします。

厚生労働省のコロナのPCR検査数データを使って移動平均の出し方を覚えます。



参考リンク

pandasで窓関数を適用するrollingを使って移動平均などを算出 | note.nkmk.me



厚労省の新型コロナPCR検査数データを読み込む

url = "https://www.mhlw.go.jp/content/pcr_tested_daily.csv"

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# ネットから直接CSVを読み込む
df=pd.read_csv(url)
df
日付 PCR 検査実施件数(単日)
0 2020/2/5 4
1 2020/2/6 19
2 2020/2/7 9
3 2020/2/8 4
4 2020/2/9 10
... ... ...
421 2021/4/4 17189
422 2021/4/5 60274
423 2021/4/6 53019
424 2021/4/7 58424
425 2021/4/8 70959

426 rows × 2 columns

CSVファイルには上記のデータが入っております。



そのままグラフ表示


検査数をそのままでグラフに表示させてみる。

x = df.iloc[:,0] #日付
y = df.iloc[:,1] #検査数

plt.plot(x,y)
plt.savefig("tested.jpg")
plt.show()

f:id:chayarokurokuro:20210409225934j:plain

このように、日によって検査数に幅があります。 (横軸は日付で真っ黒に塗りつぶれています)。見にくいですね。

もう少しおおざっぱに把握したいので、検査数を7日移動平均で出してみます。

その前に移動平均の出し方を押さえておこう。



Pandasでの移動平均の出し方


適当に10個の整数を生成し、移動平均を出してみます。

# ランダムな整数のseries生成
s = pd.Series(np.random.randint(0,11,10))
s
0     9
1     3
2     4
3    10
4     5
5     0
6     0
7    10
8     4
9     8
dtype: int64
# 3つ移動平均
s_r3mean_nan = s.rolling(window=3).mean()
s_r3mean_nan
0         NaN
1         NaN
2    5.333333
3    5.666667
4    6.333333
5    5.000000
6    1.666667
7    3.333333
8    4.666667
9    7.333333
dtype: float64
  • rolling()の第一引数に渡した値の範囲で平均値が出る。
  • 平均値の範囲に満たない部分は欠損値NaNになるが、
    • 第二引数にmin_periods=整数を与えれば欠損値をその最小~window値の範囲で埋めてくれる。
# 3つ移動平均
s_r3mean_1 = s.rolling(window=3, min_periods=1).mean()
s_r3mean_1
0    9.000000
1    6.000000
2    5.333333
3    5.666667
4    6.333333
5    5.000000
6    1.666667
7    3.333333
8    4.666667
9    7.333333
dtype: float64



連結して見やすくする。

# DataFrameに
s_df = pd.DataFrame(s)
s_df

# 結合
s_df["3つ移動平均"] = s_r3mean_1
s_df
0 3つ移動平均
0 9 9.000000
1 3 6.000000
2 4 5.333333
3 10 5.666667
4 5 6.333333
5 0 5.000000
6 0 1.666667
7 10 3.333333
8 4 4.666667
9 8 7.333333

3行目の5.333333は1~3行までの平均値、
4行目の5.666667は2~4行までの平均値、
という具合でズレながら平均値が出ます。

欠損値NaNだった1行目はそのままの値、2行目は1~2行目の平均値に、min_periodsを指定したことで置き換わっています。



以上を踏まえて、

検査数の7日移動平均を出す

# 検査数を取り出し
n = df.iloc[:,1]
n
0          4
1         19
2          9
3          4
4         10
       ...  
421    17189
422    60274
423    53019
424    58424
425    70959
Name: PCR 検査実施件数(単日), Length: 426, dtype: int64
# 検査数を7日移動平均に変換。最小範囲1で。
n_m7 = n.rolling(7, 1).mean()
n_m7
0          4.000000
1         11.500000
2         10.666667
3          9.000000
4          9.200000
           ...     
421    52239.428571
422    50538.714286
423    52220.428571
424    50933.142857
425    51730.571429
Name: PCR 検査実施件数(単日), Length: 426, dtype: float64

移動平均が出ました。



移動平均でグラフ作成

# グラフ作成
y_7 = n_m7 #縦軸
x = df.iloc[:,0] #横軸

#プロット
plt.plot(x, y_7)

# 横軸を31日おきの目盛りに
plt.xticks(x[::31], rotation=45)

# 画像保存
plt.savefig("tested_7mean.jpg")

# 表示
plt.show()

f:id:chayarokurokuro:20210409230243j:plain



そのままの値と移動平均を同時に表示させます。

y_7 = n_m7
x = df.iloc[:,0]

plt.plot(x, y, y_7)
plt.xticks(x[::31], rotation=45)
plt.savefig("tested_mix.jpg")
plt.show()

f:id:chayarokurokuro:20210409230333j:plain

matplotlibが自動的に色を変えてくれます。



おわりに


Series.rolling(window=整数, min_periods=整数).mean()
でサクッと出せて簡単ですね!

検査数を増やせば陽性者数も増えます。現在大阪府の感染者が増加しているのも、このひと月で検査数を3倍ほどに増やしているせいです。東京都は逆に全然検査していない。
検査数を見ないで陽性者数や感染者数の値だけでヤンヤン騒ぐのは馬鹿げています。医者やGoogleのデータサイエンティストでも検査数を無視して騒ぐポンコツが沢山います。マスコミは全滅です。ポンコツにも程がある。悪魔😈に魂を売り渡したんだろう。騙されないように気を付けましょう。