This vignette takes an Apple Health export (Health
app → profile → Export All Health Data →
export.xml, plus any ECG .csv files) all the
way through to per-modality analysis, using PhysioDevices
for ingestion and PhysioWearable / PhysioECG
for the analysis.
ah <- readAppleHealth("apple_health_export/export.xml", tz = "Asia/Tokyo")
ah
appleHealthTypes(ah) # what modalities are present, with counts and spansreadAppleHealth() streams the file, so multi-hundred-MB
exports are fine. Every <Record> becomes a row (type,
source, unit, start/end, value); <Workout> elements
become ah$workouts.
The watch already stores HRV as
HeartRateVariabilitySDNN; heart rate is
HeartRate. For deeper HRV from the raw beats, use the
single-lead ECG (below).
ox <- appleHealthSeries(ah, "OxygenSaturation") # fraction 0-1
PhysioWearable::spo2Metrics(ox$value_num, time = ox$start)spo2Metrics() reports mean, nadir, time-below-90%
(T90/CT90) and an oxygen desaturation index (ODI). Note the Apple Watch
takes periodic spot readings, not a continuous trace,
so ODI/T90 are approximate unless you feed continuous overnight
oximetry.
The watch scores sleep stages itself;
summarizeAppleSleep() turns them into per-night clinical
metrics (TST, efficiency, WASO, latency, stage minutes).
stages <- appleHealthSeries(ah, "SleepAnalysis") # AsleepCore/Deep/REM, Awake, InBed
PhysioWearable::summarizeAppleSleep(stages)If you instead have raw activity counts (from another wearable), score sleep/wake with the Cole-Kripke algorithm and summarise it:
steps <- appleHealthSeries(ah, "StepCount")
energy <- appleHealthSeries(ah, "ActiveEnergyBurned")
tapply(steps$value_num, as.Date(steps$start), sum) # steps per day
ah$workouts # per-workout summariesFor epoch-level free-living metrics (ENMO, intensity gradient,
fragmentation, HAR → ICF), export raw accelerometry from a Core-Motion
app and use PhysioWearable::readAccelCSV() →
summarizeFreeLiving() (Apple Health itself stores only
derived activity, not raw acceleration).
Apple Watch ECG recordings export as one CSV each;
readAppleECG() reads the single-lead trace into a
PhysioExperiment that feeds PhysioECG:
export.xml — the ECG is a separate CSV
(readAppleECG()); raw motion needs a Core-Motion capture
app.coleKripke() is for raw-count actigraphy, not a
re-scoring of Apple’s stages.tz
to your local zone.