概要
Databricks では、IoT 連携などで 横持ち(ワイド形式)になった大量のカラムを扱うことがあります。
本記事では、STACK
関数を用いて グループ単位(温度・湿度・照度)でカラムを縦持ち(ロング形式)へ変換する方法を、サンプルデータフレームを使って解説します。最終的な変換結果もあわせてご紹介します。
背景
IoT データを取り込む際、デバイス数や計測項目が増えるたびに 列が際限なく増加 し、クエリが複雑化する問題が発生します。
例として、3 台のデバイスがそれぞれ 温度・湿度・照度 を計測し、その値を個別のカラムに格納しているケースを想定します(下図参照)。
このままではデバイスや計測項目の追加時に列数が指数的に増え、テーブル設計や分析が困難になります。そこで STACK
関数 を利用し、温度・湿度・照度を 1 列ずつにまとめる 行列変換 を行います(変換後のイメージは下図)。
実装方法
1. サンプルデータフレームの作成
from datetime import datetime
data = [
{
"timestamp": datetime(2025, 6, 20),
"device1_temp": 25.1,
"device1_humid": 40.2,
"device1_lux": 350,
"device2_temp": 26.0,
"device2_humid": 41.5,
"device2_lux": 360,
"device3_temp": 24.7,
"device3_humid": 39.8,
"device3_lux": 345,
}
]
df = spark.createDataFrame(data)
display(df)
device1_humid | device1_lux | device1_temp | device2_humid | device2_lux | device2_temp | device3_humid | device3_lux | device3_temp | timestamp |
---|---|---|---|---|---|---|---|---|---|
40.2 | 350 | 25.1 | 41.5 | 360 | 26 | 39.8 | 345 | 24.7 | 2025-06-20T00:00:00.000+00:00 |
2. STACK
関数で行列変換
from pyspark.sql import functions as F
out_df = (
df
.select(
"timestamp",
F.stack(
F.lit(3),
F.lit("device1"), F.col("device1_temp"), F.col("device1_humid"), F.col("device1_lux"),
F.lit("device2"), F.col("device2_temp"), F.col("device2_humid"), F.col("device2_lux"),
F.lit("device3"), F.col("device3_temp"), F.col("device3_humid"), F.col("device3_lux"),
).alias("device", "temperature", "humidity", "illuminance")
)
)
display(out_df)
timestamp | device | temperature | humidity | illuminance |
---|---|---|---|---|
2025-06-20T00:00:00.000+00:00 | device1 | 25.1 | 40.2 | 350 |
2025-06-20T00:00:00.000+00:00 | device2 | 26.0 | 41.5 | 360 |
2025-06-20T00:00:00.000+00:00 | device3 | 24.7 | 39.8 | 345 |
まとめ
本記事の方法により、各デバイス・計測項目を 縦持ち に統合でき、列の爆発を防ぎつつシンプルにクエリを記述できます。必要に応じて STACK
の引数にデバイス数を増やすだけで拡張できるため、スケーラビリティも確保できます。