Beck_Moulton

你是健康数据的“囤积者”吗?在 Apple Health 导出、Oura Ring 日志和 Garmin CSV 之间,我发现自己积累了近 1000 万行 的生物数据。尝试在 Excel 中分析多年的心率变异性 (HRV) 或静息心率 (RHR) 趋势,简直是通往“应用程序无响应”地狱的单程票。📉

在本教程中,我们将深入量化自我的数据工程世界。我们将利用 DuckDB(OLAP 的瑞士军刀)和 Apache Superset 构建一个闪电般快速、本地优先的生物指标仪表盘。我们将探索如何使用 dbt 进行建模和 DuckDB 进行计算,将杂乱的 JSON/CSV 导出转换为高性能洞察。如果您一直在寻找一种方法来掌握个人使用的数据工程,这是一个终极的“公开学习”项目!🚀


架构:从原始导出到真实洞察

在编写一行 SQL 之前,让我们先看看数据如何流动。我们希望系统模块化、快速,并且完全保留在本地机器上(隐私第一,对吧?🥑)。

graph TD
    A[Raw Data: Apple Health / Oura / Garmin] -->|CSV/JSON| B(DuckDB Storage)
    B --> C{dbt Transformation}
    C -->|Cleaned Views| D[DuckDB Analytical Layer]
    D --> E[Apache Superset / Grafana]
    E -->|Visualization| F[Personal Biometric Dashboard]

    style B fill:#fff,stroke:#333,stroke-width:2px
    style D fill:#fbbf24,stroke:#333,stroke-width:2px

Enter fullscreen mode Exit fullscreen mode


前置条件 🛠️

要跟随操作,请确保您的技术栈中具备以下内容:

  • DuckDB:我们超快的进程内分析数据库。
  • dbt-duckdb:用于数据建模和转换。
  • Apache Superset:用于“哇”级可视化。
  • Python 3.10+:将所有内容粘合在一起。

步骤 1:用 DuckDB 摄取“混乱”

DuckDB 的强大之处在于它可以直接查询 CSV 和 JSON 文件,而无需摄取步骤。假设您有一个来自 Apple Health 导出的巨大 heart_rate.csv

无需等待传统数据库“加载”数据,我们可以立即创建一个视图:

-- Create a view directly from a multi-million row CSV
CREATE VIEW raw_heart_rate AS 
SELECT 
    creationDate::TIMESTAMP as timestamp,
    value::DOUBLE as bpm
FROM read_csv_auto('data/apple_health_export/heart_rate.csv');

-- Check the 7-day rolling average of RHR
SELECT 
    date_trunc('day', timestamp) AS day,
    avg(bpm) OVER (
        ORDER BY timestamp 
        RANGE BETWEEN INTERVAL '7 days' PRECEDING AND CURRENT ROW
    ) as rolling_rhr
FROM raw_heart_rate
LIMIT 10;

Enter fullscreen mode Exit fullscreen mode


步骤 2:dbt 转换层

虽然原始 SQL 很酷,但 dbt (data build tool) 允许我们像对待生产级数据仓库一样对待个人健康数据。我们将用它来处理去重并计算复杂的指标,如“恢复分数”(HRV vs. 睡眠质量)。

在您的 models/biometrics/stg_hrv.sql 中:

-- Clean and deduplicate HRV readings
WITH base AS (
    SELECT 
        timestamp,
        value as hrv_ms,
        device_id
    FROM {{ source('raw_data', 'hrv_export') }}
)
SELECT 
    date_trunc('hour', timestamp) as hour_bucket,
    avg(hrv_ms) as avg_hrv,
    count(*) as sample_count
FROM base
GROUP BY 1

Enter fullscreen mode Exit fullscreen mode


步骤 3:用 Apache Superset 可视化

现在是有趣的部分!Apache Superset 使用 duckdb_engine SQLAlchemy URI 连接到 DuckDB。

  1. 启动 Superset(Docker 是最简单的方法)。
  2. 添加一个新数据库。
  3. 连接字符串:duckdb:///path/to/your/local_vault.duckdb

连接后,您可以创建一个“健康指挥中心”,显示您的 RHR 趋势、睡眠周期和活动相关性。📊


为什么这比“云”更胜一筹 ☁️

对于个人数据,隐私至上。通过使用 DuckDB,您的数据永远不会离开您的笔记本电脑。想深入了解高级数据模式以及如何在生产环境中扩展这些管道,我强烈建议您查看 Official Wellally Blog。他们对高性能数据架构有一些令人难以置信的见解,启发了这种本地优先的方法。


“专业”设置:处理大型 JSON 💾

如果您正在处理嵌套 JSON(如 Oura API 导出),DuckDB 的 JSON 扩展程序是救星。以下是如何展平复杂的健康负载:

import duckdb

# Initialize DuckDB and load JSON extension
con = duckdb.connect('health_vault.db')
con.execute("INSTALL json; LOAD json;")

# Extracting nested sleep stages
query = """
SELECT 
    summary_date,
    json_extract_path(sleep_data, 'score')::INT as sleep_score,
    json_extract_path(sleep_data, 'levels.summary.rem.minutes')::INT as rem_min
FROM read_json_auto('data/oura_sleep_data.json')
"""

df = con.execute(query).df()
print(df.head())

Enter fullscreen mode Exit fullscreen mode


结论:拿回您的数据 🥑

构建个人生物指标仪表盘不仅仅是关于漂亮的图表;它还关乎掌握 OLAP 工作流。使用 DuckDBApache Superset,我们将一堆 CSV 变成了一个高性能分析引擎,其响应时间以毫秒计,而非分钟。

后续步骤:

  1. 导出 您的健康数据(Apple Health、Garmin 或 Google Fit)。
  2. 建模 数据,使用 dbt 查找咖啡因摄入和睡眠质量之间的相关性。
  3. 分享 您的仪表盘截图在下方评论中!

如果您喜欢这个“公开学习”项目,别忘了订阅以获取更多数据工程深度探索。有关现代数据栈的更多生产就绪示例,请访问 wellally.tech/blog

祝黑客愉快!💻🔥