管理人Kのひとりごと

デジモノレビューやプログラミングや写真など

pysparkでFitbitの歩数JSONをパースして平日と休日の平均歩数を求めてみた

pysparkでFitbitの歩数JSONをパースして、平日と休日の平均歩数を求めてみました。

pysparkでの歩数JSONのパース↓

pythonでの歩数比較↓
www.k-hitorigoto.online

確認環境

import sys
print(sys.version)
3.8.6 | packaged by conda-forge | (default, Dec 26 2020, 05:05:16) 
[GCC 9.3.0]

print(spark.version)
3.0.1

コード

文字列だった日付を日付型に変換したのち、月、曜日、平日、休日フラグ列を追加したテーブルを作成。それを集計することで月別、平日・休日別の平均歩数をSQLで集計しました。

from pyspark.sql import SparkSession
from pyspark.sql import functions

spark = SparkSession \
    .builder \
    .enableHiveSupport() \
    .getOrCreate()
    
df = spark.read.json('/tmp/year_2020.json')

# 要素[dateTime,value]を行に分割したカラムを作成
col = functions.explode(functions.col('activities-steps'))

# 元のデータ列の横にカラムを追加
df = df.withColumn('lines',col)

# 元のデータ列を削除
df = df.drop("activities-steps")

# dateTime,valueのデータフレームに変換
df = df.select(functions.col("lines.dateTime").alias("strDateTime"),"lines.value")

#  strDateTimeをパースして日付型にした列の追加
df = df.withColumn("dateTime", functions.to_timestamp("strDateTime", 'yyyy-MM-dd'))

# strDateTimeを削除して、dateTime,valueでDF再作成
df = df.select("dateTime", "value")

# dateTimeを基に、曜日列、月列を追加
df = df.withColumn("dayOfWeek", functions.date_format("dateTime", 'E'))
# 月はそのままだと文字列扱いなので数値にキャスト
df = df.withColumn("month", functions.date_format("dateTime", "M").cast("integer"))

# dayOfWeekを基に平日と週末を区別する列を追加
df = df.withColumn("is_weekday", 
                   functions.when((functions.col("dayOfWeek") == "Sat") | (functions.col("dayOfWeek") == "Sun"), 0).otherwise(1))

# DFをSQLで操作するため、テーブル登録
df.registerTempTable("steps_2019")

# dataframeの表示
df.show()

# 月別の平日、休日ごとの歩数平均を集計
# filterを使って集計対象範囲を限定
sql = """
select
    month
   ,round(avg(value) filter(where is_weekday = 1), 1)as avg_weekday
   ,round(avg(value) filter(where is_weekday = 0), 1) as avg_weekend
from
    steps_2019
group by
    month
order by
    month
"""

df = spark.sql(sql)

# dataframeの表示
df.show()

実行結果例

# 集計元テーブル
+-------------------+-----+---------+-----+----------+
|           dateTime|value|dayOfWeek|month|is_weekday|
+-------------------+-----+---------+-----+----------+
|2020-01-01 00:00:00| 5179|      Wed|    1|         1|
|2020-01-02 00:00:00| 8387|      Thu|    1|         1|
|2020-01-03 00:00:00|18740|      Fri|    1|         1|
|2020-01-04 00:00:00| 7037|      Sat|    1|         0|
|2020-01-05 00:00:00| 5392|      Sun|    1|         0|
|2020-01-06 00:00:00| 7081|      Mon|    1|         1|
|2020-01-07 00:00:00| 7315|      Tue|    1|         1|
...

# 集計結果テーブル
+-----+-----------+-----------+
|month|avg_weekday|avg_weekend|
+-----+-----------+-----------+
|    1|     9708.3|     8414.1|
|    2|     9396.2|     8909.2|
|    3|     9789.9|     7861.6|
|    4|     3967.2|     9067.5|
...

2019年、2020年の月別、平日・休日別平均歩数

2019_平日 2019_休日 2020_平日 2020_休日
1 6959.2 8497.3 9708.3 8414.1
2 7528.9 9900.4 9396.2 8909.2
3 8818.9 9082.3 9789.9 7861.6
4 8774.3 9723.5 3967.2 9067.5
5 7829.3 8446.4 6073.6 8210.1
6 7271.7 9727.4 5259.0 10724.6
7 7884.3 7851.3 5517.6 8943.5
8 7979.5 8737.2 5268.8 9373.4
9 7785.0 8893.8 5280.5 8368.1
10 7676.4 9320.0 3804.2 9927.1
11 8309.2 9272.8 3488.5 10715.1
12 9141.7 9605.4 3388.7 12626.4

f:id:ksk1130:20210118001904p:plain
2019年は平日と休日の平均歩数の差が小さいですが(休日は平日の約10~20%増)、2020年は4月以降休日と平日の差が顕著になってますね。特に、2020年10月以降は平日と休日の差が約3倍にも開いてます。平日の歩数不足を休日の散歩等でカバーしようとした結果が表れていますね...

参考にしました