2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

時系列データの集計を練習するチュートリアル

Last updated at Posted at 2025-06-24

概要

センサーデータを収集したとき、その分析では全体をプロットして終わりではなく、時間ごと・日ごとなどの時間軸で集計して傾向を把握したいことがあります。集めたデータの1件ごとにタイムスタンプを付与しておけば、もともとのデータが等間隔でなくとも、うまく処理する方法があります。
ここでは、時系列のレコードをいったん解きごたえがあるように加工し、その集計を試みます。

対象とする元データ

Kaggleには様々なデータセットが公開されています。今回は、まさに練習用と銘打たれたデータを見つけたので、これをもとに操作していきます。

(事前の加工)

適当な秒数のインターバル、1年分でかつ、9:00-21:00の範囲にdatetimeを付与しました。

## 加工のコード
def get_interval():
    ## データ点数を1日12時間x365に分けたとき、点の間の時間幅はおよそ69秒なので、平均69の乱数をとる
    return int(np.random.random() * 138)

df = pd.read_csv("train.csv")
start = pd.to_datetime("2025-01-01T09:00")
prev = start
datetimes = [start]
for i in range(1,230090):
    next_time = prev + pd.to_timedelta("1sec") * get_interval()
    if next_time.hour >= 21:
        #21:00すぎたら次の日のデータとする
        new_day = pd.to_datetime(next_time.strftime("%Y-%m-%d"))+pd.to_timedelta("1day")
        diff = next_time - (pd.to_datetime(next_time.strftime("%Y-%m-%d"))+pd.to_timedelta("21hour"))
        next_time = new_day + pd.to_timedelta("9hour") + diff
    datetimes.append(next_time)
    prev = next_time
df["datetime"] = datetimes

# やけに数値が低いデータが混じっているので、その範囲だけ一律+600する
sub = df.loc[np.logical_and("2025-06-06"<=df["datetime"],df["datetime"]<="2025-07-28"),["datetime","number_sold"]]
low_index = sub.loc[sub.number_sold < 500].index
df.loc[low_index,["number_sold"]] += 600
df.to_csv("modified_data.csv")

加工の結果、程よく変動する1年分のデータになりました。
image.png

Pandasで読み込む

事前加工ですでに使っていますが、今回の集計にはpandasを利用します。pd.to_datetime()pd.to_timedelta() が時系列データの加工に便利です。

df = pd.read_csv("modified_data.csv")
# 扱う対象をシンプルなものに限定、datetimeと数量[number_sold]のみに
df = df.loc[:,["datetime","number_sold"]]

さて、特に指定せずに読み込むと、datetimeの列のdtypeはobjectになっていて、時刻として処理しにくいです。そこで、pd.to_datetime()で変換しておきます。

df["datetime"] = pd.to_datetime(df["datetime"])

dfは次のようになります。

datetime	number_sold
0	2025-01-01 09:00:00	801
1	2025-01-01 09:01:01	810
2	2025-01-01 09:01:08	818
3	2025-01-01 09:02:02	796
4	2025-01-01 09:03:05	808

一定間隔の集計

インターバルをランダム化したため、datetimeの間隔はまちまちです。これを分単位に集計してみましょう。

df.resample("1min",on="datetime").sum()
	number_sold
datetime	
2025-01-01 09:00:00	801
2025-01-01 09:01:00	1628
2025-01-01 09:02:00	796
2025-01-01 09:03:00	1620
2025-01-01 09:04:00	830
...	...
2025-12-31 12:38:00	890
2025-12-31 12:39:00	0
2025-12-31 12:40:00	892
2025-12-31 12:41:00	895
2025-12-31 12:42:00	1811

1分おきに、データを集計できました。.resample()のパラメータを変えていけば、当然好きな間隔で集計することができます。
例) 1時間なら "1h" 1日なら "1d"など。

一定間隔の集計ができたので、各単位ごとの平均値を集計することは簡単にできます。

minute_average = df.resample("1min",on="datetime").sum().mean()
print("1分あたりの数量1平均:",minute_average)

時間帯ごとの集計

ここで、11時台の平均値を求めることを考えます。1時間あたりの平均は出せても、前項の集計方法では個別の時間帯ごとの値にはなりません。
ここで、datetimeがdatetime形式になっていることが役立ちます。値そのものに.hourで時間を返すパラメータがあります。これを使って、hourを設定し、それをgroupbyで取り出せば、平均値を出せます。

df_hourly = df.resample("1h",on="datetime").sum()
# resampleでdatetimeがindexに移動していることに注意
df_hourly["hour"] = df_hourly.index.hour
df_hourly.groupby("hour").mean().loc[range(9,21)]

この結果は以下の通りです。

	number_sold
hour	
9	45377.931507
10	45631.841096
11	45625.893151
12	45796.443836
13	45838.162088
14	45467.587912
15	45690.829670
16	45702.994505
17	45344.662088
18	45821.774725
19	45393.612637
20	45623.804945

同様に、1日ごとのデータに直して、各月の1日平均を出すと、

df_daily = df.resample("1d",on="datetime").sum()
df_daily["month"] = df_daily.index.month
df_daily.groupby("month").mean()
	number_sold
month	
1	544746.290323
2	501459.000000
3	454676.354839
4	480952.233333
5	522399.225806
6	584870.366667
7	598112.129032
8	612879.258065
9	592174.900000
10	567799.451613
11	548664.466667
12	543405.903226

1時間ごとは、今回の加工だと変動が見えませんでしたが、月ごとには変動の様子が見えています。
時間帯別と月別では、単純な集計単位の変更とは違っていたことに注意してください
(時間帯ごとの1時間平均では1時間ごとの合計値を出してから、時間帯別に平均をとりました。一方で、月別平均では1か月おきの合計値にしてしまうと、XX月の平均、とは異なる値になってしまうので、1日ごとの合計値にして、各日付のXX月をとりだし、その月別に平均をとる必要がありました。)

まとめ

1分当たり、時間帯ごと、月ごと、などの集計をするときに、Pandasが便利です。
resampleでデータの粒度と、平均や合計する範囲については、集計軸に応じて考慮が必要です。

今回は以上です。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?