--- title: "Getting started with syncR" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Getting started with syncR} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", message = FALSE, warning = FALSE ) library(syncR) library(dplyr) ``` ## Overview syncR is the integrator and coordinator of the Circadia Lab R ecosystem. > *syncR::sync() — pulling everything into alignment, just like the SCN does.* The `sync()` function pulls three streams of participant data into a single unified, participant-indexed database: | Argument | Package | Typical source function | Data type | |---|---|---|---| | `tallie` | **tallieR** | `scores_wide()` | Sociodemographics + questionnaire scores | | `slumb` | **slumbR** | `diary_wide()` | Sleep diary entries, subjective sleep quality | | `zeit` | **zeitR** | `study_summary()` | Actigraphy metrics, circadian parameters | --- ## Test data This vignette uses the built-in test data bundled with syncR, which mirrors the real output of each package. Load it with `readRDS()`: ```{r load-data} tallie <- readRDS(system.file("testdata/tallie_test.rds", package = "syncR")) slumb <- readRDS(system.file("testdata/slumb_test.rds", package = "syncR")) zeit <- readRDS(system.file("testdata/zeit_test.rds", package = "syncR")) ``` ### tallieR data One row per participant, with demographics and questionnaire scores from `tallieR::scores_wide()`: ```{r show-tallie} dplyr::glimpse(tallie) ``` Key fields: `participant_id` (the join key), sociodemographic variables (`age`, `sex`, `bmi`, `group`), and instrument scores (`ess_score`, `isi_score`, `meq_score`). ### slumbR data One row per participant per night, from `slumbR::diary_wide()` + `slumbR::compute_sleep_vars()`. Morning columns are prefixed `m_` and evening columns `e_`. Seven nights across five participants gives 35 rows: ```{r show-slumb} dplyr::glimpse(slumb) ``` Key morning fields: timing (`m_bed_time`, `m_rise_time`, `m_sol_min`), derived sleep variables (`m_tib_min`, `m_tst_min`, `m_se_pct`), substance use (`m_alcohol_drinks`, `m_sleep_aid_used`), clinical flags (`m_sol_flag`, `m_waso_flag`, `m_tst_flag`, `m_se_flag`), and subjective ratings (`m_sleep_quality`, `m_restedness`). Key evening fields: napping (`e_nap_taken`, `e_nap_duration_min`), substance use (`e_caffeine_drinks`, `e_sleep_med_used`), and activity (`e_exercised`). ### zeitR data One row per participant, from `zeitR::study_summary()`: ```{r show-zeit} dplyr::glimpse(zeit) ``` Key circadian fields: `IS` (interdaily stability), `IV` (intradaily variability), `RA` (relative amplitude), `L5` / `L5_onset`, `M10` / `M10_onset`. --- ## Synchronising with `sync()` ### Default left join The default call performs a **left join** anchored on the first supplied source. Since `slumb` has multiple rows per participant, the result expands to one row per participant per night — with questionnaire scores and circadian variables repeated across all nights for each participant: ```{r sync-default} db <- sync( tallie = tallie, slumb = slumb, zeit = zeit ) dim(db) ``` ```{r sync-preview} db |> dplyr::select( participant_id, date, age, sex, ess_score, isi_score, meq_score, m_tst_min, m_se_pct, m_sleep_quality, IS, IV, RA ) |> head(10) ``` ### Inner join Use `join = "inner"` to retain only participants present in **all three** sources: ```{r sync-inner} db_inner <- sync( tallie = tallie, slumb = slumb, zeit = zeit, join = "inner" ) nrow(db_inner) ``` ### Full join Use `join = "full"` to retain **all** participants from any source, filling `NA` where data is absent: ```{r sync-full} db_full <- sync( tallie = tallie, slumb = slumb, zeit = zeit, join = "full" ) nrow(db_full) ``` ### Custom participant ID column If your data uses a different column name, pass it via `id_col`: ```{r sync-idcol, eval = FALSE} db <- sync( tallie = my_tallie_data, slumb = my_slumb_data, zeit = my_zeit_data, id_col = "pid" ) ``` ### Partial sync All sources are optional — pass only what you have: ```{r sync-partial} db_partial <- sync( tallie = tallie, zeit = zeit ) dim(db_partial) ``` --- ## Example analyses With a unified database, cross-domain analyses require no further joining. ### Circadian type vs. sleep efficiency MEQ chronotype score against actigraphy-derived IS and mean subjective sleep efficiency: ```{r analysis-chronotype} db |> dplyr::group_by(participant_id) |> dplyr::summarise( meq_score = dplyr::first(meq_score), IS = dplyr::first(IS), mean_se_pct = mean(m_se_pct, na.rm = TRUE), mean_quality = mean(m_sleep_quality, na.rm = TRUE), .groups = "drop" ) |> dplyr::arrange(dplyr::desc(meq_score)) ``` ### Insomnia severity vs. objective sleep ISI score against mean TST and WASO from the diary: ```{r analysis-insomnia} db |> dplyr::group_by(participant_id) |> dplyr::summarise( isi_score = dplyr::first(isi_score), mean_tst_h = mean(m_tst_min, na.rm = TRUE) / 60, mean_waso_min = mean(m_waso_min, na.rm = TRUE), mean_se_pct = mean(m_se_pct, na.rm = TRUE), .groups = "drop" ) |> dplyr::arrange(dplyr::desc(isi_score)) ``` ### Substance use and sleep quality Nights with alcohol consumption or sleep aid use, and their impact on next- morning sleep quality and efficiency: ```{r analysis-substances} db |> dplyr::mutate( any_substance = m_alcohol_drinks > 0 | m_sleep_aid_used | e_caffeine_drinks > 3 ) |> dplyr::group_by(any_substance) |> dplyr::summarise( n_nights = dplyr::n(), mean_tst_h = mean(m_tst_min, na.rm = TRUE) / 60, mean_se_pct = mean(m_se_pct, na.rm = TRUE), mean_waso_min = mean(m_waso_min, na.rm = TRUE), mean_quality = mean(m_sleep_quality, na.rm = TRUE), .groups = "drop" ) ``` ### Nights with poor sleep efficiency Flagging nights where SE < 85%, alongside each participant's circadian profile: ```{r analysis-flags} db |> dplyr::filter(m_se_flag == TRUE) |> dplyr::select( participant_id, date, m_tst_min, m_se_pct, m_alcohol_drinks, m_sleep_aid_used, IS, RA ) |> dplyr::arrange(m_se_pct) ``` --- ## Working with real data In a real study, the inputs to `sync()` come directly from the package export functions: ```{r real-data, eval = FALSE} library(tallieR) library(slumbR) library(zeitR) library(syncR) tallie <- tallieR::read_scoreme("exports/scoreme_export.json") |> tallieR::scores_wide() slumb <- slumbR::read_study("exports/sleep_diaries/") |> slumbR::diary_wide() zeit <- zeitR::read_actigraphy_dir("recordings/", tz = "Europe/London") |> zeitR::study_summary() db <- sync( tallie = tallie, slumb = slumb, zeit = zeit ) ``` --- ## Session info ```{r session-info} sessionInfo() ```