Sleep Cycle Nocturnal Coughs

Attribute Details
Source Name sleepcycle
Data Source Nocturnal cough rates from the Sleep Cycle sleep-tracking app
Geographic Levels county, hrr, msa, state, hhs, census_division, census_region, nation
Temporal Granularity Daily
Reporting Cadence Daily
Temporal Scope Start 2023-01-07
Temporal Scope End Ongoing
Extra Key Columns None
License CC BY-NC 4.0

Table of contents

  1. Overview
  2. Indicators (Signals)
  3. Estimation
    1. Metric Definition
    2. Smoothing
    3. Uncertainty
    4. Temporal Handling
    5. Geographic Handling
  4. Schema
    1. Columns
  5. Missingness & Privacy
  6. Limitations
  7. Lag & Backfill
  8. Source and Licensing

Overview

This source measures the frequency of moderate and very high nocturnal cough rates. It is built from de-identified data from the Sleep Cycle sleep tracking app, contributed by parent company Sleep Cycle. Since the data captures symptoms, it can be used for many respiratory pathogens, including influenza and COVID-19, as well as other medical and environmental conditions that may contribute to coughing, for example, wildfire smoke. This source is noised at the epsilon = 1 level per user-day under differential privacy (DP).


Indicators (Signals)

Indicator Name Pathogen or Disease Metric Type Description
pct_cough_2_plus_7dav N/A Percentage, 7-day window Percent of users who coughed 2 or more times an hour (on average) while sleeping.
pct_cough_10_plus_7dav N/A Percentage, 7-day window Percent of users who coughed 10 or more times an hour (on average) while sleeping.

Estimation

Metric Definition

To prevent reidentification of participating users, this dataset is noised in a way that makes it differentially private at the epsilon = 1 level per user per day. (What does epsilon = 1 mean? See discussion of “updated probability” here.) We noise numerators for each indicator with epsilon = 1/2 and sensitivity delta = 1. This results in us applying Laplacian noise with location = 0 and scale = 2. The noise has units of counts.

New noise values are drawn for every county \(i\) and time \(t\). Once a county \(i\) and time \(t\) key has a noise value assigned, that noise value is reused for every issue made to that county and time key’s value.

Only raw county numerators are noised with randomly drawn DP-conforming noise. This is done before any geoaggregation or smoothing is performed. Denominators are left unnoised.

When a raw value is close to a natural threshold (for numerator, 0 or \(n_i\)) or the noise is relatively large, the noised value can become impossible (< 0, > \(n_i\)). These values are left as-is until after geoaggregation, smoothing, and percentage calculation are done, after which impossible percentages are truncated to the closest boundary (0, 100). Early truncation biases aggregated values.

For county \(i\) and time \(t\), with numerator count \(Y_{it}\), denominator \(N_{it}\), and DP noise \(\delta_{it}\) (in count units),

\[\hat{p}_{it} = 100 \cdot \frac{Y_{it} + \delta_{it}}{N_{it}}.\]

These metrics only include users who used the app on a given day and agreed to share their data. The numerator counts the number of users whose average hourly nocturnal cough rate was greater than x. Average hourly cough rate for a user is calculated as total number of coughs while sleeping divided by total number of hours slept. This includes any kind of sleep – sleeping overnight, but also napping, increased sleeping while sick, etc.

For non-county location \(i\) and time \(t\), with estimated numerator count \(Y'_{it}\), denominator \(N_{it}\),

\[\hat{p}_{it} = 100 \cdot \frac{Y'_{it}}{N_{it}}.\]

Estimated numerator count \(Y'_{it}\) for a non-county location incorporates DP noise via the geoaggregation process.

Smoothing

Smoothing is computed by Delphi. For each geography, a 7-day trailing sum is computed over the noised numerator count and the total user count (denominator), from which the percentage is then calculated. The resulting smoothed metric is equivalent to the denominator-weighted pooled percentage. The 7-day window must contain at least 5 of 7 days to produce a value.

Uncertainty

This source provides 90% (\(z = 1.645\)) confidence intervals for all indicators via the ci_upper and ci_lower columns. Because cough indicators are binomial percentages, we report Wilson score intervals inflated by the DP noise variance. The confidence intervals are estimated as

\[100 \cdot \frac{\hat{p} + \frac{z^2}{2N} \pm z \sqrt{\frac{\hat{p}(1 - \hat{p})}{N} + \frac{z^2}{4N^2} + c \left(1 + \frac{z^2}{N}\right)}}{1 + \frac{z^2}{N}}\]

Subtracting gives ci_lower and adding gives ci_upper. Compared to a standard Wilson interval, the term \(c \left(1 + \frac{z^2}{N}\right)\) inflates the interval to account for DP noise, where \(c = \frac{\sigma^2_{\text{noise}}}{N^2}\) scales the numerator noise variance \(\sigma^2_{\text{noise}}\) to proportion units.

This approach preserves nominal 90% coverage in the presence of differential privacy noise while keeping the intervals well-behaved near 0% and 100%.

Temporal Handling

Observations cover single calendar days. Each value reflects nocturnal cough events recorded during sleep sessions attributed to that date.

  • reference_time is the observation date (YYYY-MM-DD). For 7-day smoothed indicators (_7dav), reference_time marks the final date of the trailing 7-day window.
  • report_time is the ingestion timestamp in UTC. Sleep Cycle refreshes data upstream approximately every four hours (six times per day).

Geographic Handling

Cough data arrives at one native geographic level: county (county). Only raw county numerators are noised with randomly drawn DP-conforming noise. This is done before any geoaggregation or smoothing is performed. Denominators are left unnoised.

All other geographic levels (msa, hrr, state, hhs, census_division, census_region, nation) are constructed by directly summing daily county counts – denominators and DP-noised numerators are aggregated separately. Aggregation is performed on noised daily counts without imputation, so fill_method is always source. Seven-day sums are computed from aggregated daily counts.

This source has good coverage at the county level. In the month of Sept 2026, values were reported for 3030 counties (of 3143 total) on at least one day. However, we restrict locations from being reported when we consider them to be too noisy, sparse, or generally not useful. See the Missingness & Privacy section for more information.


Schema

Columns

Column Key Type Data Type Description
signal Primary Key string The name of the requested indicator.
report_time Primary Key datetime Ingestion timestamp in UTC (YYYY-MM-DD HH:MM:SS).
geo_type Primary Key string Geographic level (e.g., county, state).
geo_value Primary Key string Unique code for the location (e.g., FIPS, state abbreviation).
fill_method Primary Key string Imputation method used during geographic aggregation (source, fill_ave, or fill_zero).
reference_time Primary Key date The date or surveillance period represented by the observation (YYYY-MM-DD).
value Value Column float The recorded measurement (e.g., count, percentage, rate, or statistical estimate).
ci_lower Value Column float Lower bound of the 90% confidence interval.
ci_upper Value Column float Upper bound of the 90% confidence interval.

Missingness & Privacy

Under the guarantees of differential privacy, we are able to release values for all locations, even those with very small sample sizes. However, we restrict locations from being reported when we consider them to be too noisy, sparse, or generally not useful. For example, a signal for a given location with a confidence interval of 0-100% isn’t useful and will not be reported.

Because of this, as of Oct 7 2026, we only report 258 counties, 151 HRRs, 136 MSAs, and 43 states. All locations are reported for higher geographic types (census division, census region, nation).


Limitations

These indicators are calculated using only app users who used the Sleep Cycle app on a given day and agreed to share their data.

It’s not clear how representative this data is of the general US population, for example, in terms of age and race/ethnicity. Since it is phone app-based data collection, we might expect it to skew young and/or urban.

Sleep Cycle reports some demographics in Appendix:Table 1 of this paper. Note however that reporting demographics is optional and most users do not do it. Demographics are likely subject to reporting bias.

We expect there to be day-of-week effects in the dataset. For example, people tend to sleep in on the weekends. Sick people are also more likely to sleep for a longer period of time. It’s not clear how that affects cough rate, however.

The use of differential privacy does increase the variance of the data, but it is done in an unbiased way that doesn’t obscure medium to long-term trends. It also doesn’t obscure revision behavior, since the DP noise \(\delta_{it}\) for county \(i\) and time \(t\) is reused for every issue made to that county and time’s value.

Sleep Cycle also uses differential privacy to obscure user locations. All latitude-longitude coordinates collected in the app are automatically perturbed with Laplacian noise on the user’s phone. The Laplacian noise has a standard deviation of about 500 meters. This is small compared to the size of most US counties so we don’t expect it to change estimates very much. Counties are smaller in US territories and in the state of Virginia, so values for sub-state locations in those regions may have increased uncertainty.


Lag & Backfill

Since this is digital surveillance, we expect revisions to be minimal within a matter of days. We see revisions to indicator values within 24 hours of the first time an observation (location-date key) is reported.

The only additional source of revisions we expect to see is users re-connecting to the internet after a period of using the app offline. That would send the last n days of their data to Sleep Cycle, causing aggregate estimates for those same days to be revised. Although this is possible, it’s unlikely that a user would be totally offline for more than a couple days, and even more unlikely that enough users would be offline at the same time to cause a noticeable shift in estimates. In reality, we haven’t yet seen any revisions that modify reference dates from more than 1 day ago.

Data is updated 6 times a day, and revisions within the first few updates are large.

Data is reported with less than 1 day of lag. That is, we start getting reports about what happened on reference date t on date t. Note: This means that early versions of a value are based on partial information.


Source and Licensing

De-identified digital surveillance contributed by Sleep Cycle. This dataset is made available under CC BY-NC 4.0. It may not be used for commercial purposes.