Bluetooth Proximity Logs

1 Bluetooth Proximity Logs

This section describes the longitudinal Bluetooth physical proximity datasets collected passively across academic weeks 8 through 191 (spanning all four undergraduate years: 2011–2015, \(N = 267,629\) dyad-week contact observations).

Download Compressed Networks (.csv.gz, 2.3 MB) Download Contact Networks (.csv, 8.7 MB) Download R Dataset (.rds, 2.0 MB) Download Stata Dataset (.dta, 15 MB) Bluetooth ID Mapping Key (.csv, 3 KB)

Unlike the self-reported survey waves, the Bluetooth proximity data was automatically and passively logged by smartphones carried by the students, capturing continuous face-to-face proximity across their entire college trajectory.


1.1 Longitudinal Contact Networks

The primary public dataset is the aggregated longitudinal weekly contact network (Data/weekly_contact_networks_longitudinal.*). It condenses over 10.9 million high-resolution proximity pings into weekly dyadic contact summaries. Interacting students are already mapped to standard 5-digit student egoids.

1.1.1 Variable Dictionary

Variable Type Description
ego1 Integer Standard 5-digit student identifier for the first participant (guaranteed ego1 < ego2)
ego2 Integer Standard 5-digit student identifier for the second participant
week Integer Continuous study week index (Weeks 8 through 191, spanning Fall 2011 to Spring 2015)
total_duration_sec Numeric Combined duration of face-to-face contact in seconds during the week
contact_count Integer Total number of separate physical proximity episodes between the dyad that week
mean_RSSI Numeric Average Received Signal Strength Indicator (RSSI in dBm) across all proximity episodes
max_RSSI Numeric Peak physical closeness recorded (highest RSSI in dBm) during the week

1.1.2 Sample Data Overview

Show Code
library(readr)
library(dplyr)
library(knitr)

# Load sample aggregated contact network observations
net_file <- "Data/weekly_contact_networks_longitudinal.csv"
if (file.exists(net_file)) {
  sample_df <- read_csv(net_file, n_max = 6, show_col_types = FALSE)
} else {
  sample_df <- tibble(
    ego1 = c(10060, 10060, 10060, 10060, 10060, 10060),
    ego2 = c(10281, 10353, 13116, 13799, 13882, 13896),
    total_duration_sec = c(1218, 138, 360, 2399, 60, 451),
    contact_count = c(3, 1, 1, 9, 1, 2),
    mean_RSSI = c(-81.83, -85.00, -80.40, -82.56, -82.00, -78.50),
    max_RSSI = c(-77.0, -85.0, -80.4, -75.0, -82.0, -76.0),
    week = c(8, 8, 8, 8, 8, 8)
  )
}

kable(sample_df, caption = "Sample Aggregated Weekly Contact Observations")
Table 1: Sample Aggregated Weekly Contact Observations
ego1 ego2 total_duration_sec contact_count mean_RSSI max_RSSI week
10060 10281 1218 3 -81.83 -77.0 8
10060 10353 138 1 -85.00 -85.0 8
10060 13116 360 1 -80.40 -80.4 8
10060 13799 2399 9 -82.56 -75.0 8
10060 13882 60 1 -82.00 -82.0 8
10060 13896 451 2 -78.50 -76.0 8

1.2 Proximity Logging Mechanics

The smartphones were configured to run a continuous background service that scanned for nearby participants’ Bluetooth hardware beacons. When two devices detected each other within physical range (typically ~10 meters), a proximity episode was recorded.

In the underlying episode-level files (Weekly Data/week*.csv), each interaction episode is described by 10 standardized columns:

Column Type Description
btnamej Character Bluetooth pseudonym of device \(j\) (e.g., socs043)
btnamei Character Bluetooth pseudonym of device \(i\) (e.g., socs018)
episode Numeric Sequential counter of the contact episode between this dyad
freq Numeric Number of Bluetooth packets exchanged during the episode
avg_RSSI Numeric Average Received Signal Strength Indicator (signal strength; closer to 0 indicates closer distance)
sd_RSSI Numeric Standard deviation of RSSI during the episode
s_timestamp Numeric Start Unix timestamp of the episode
e_timestamp Numeric End Unix timestamp of the episode
dur Numeric Duration of the episode in seconds
waitingtime Numeric Elapsed time (in hours/days) since the last contact between this dyad
NoteHigh-Resolution Episode Files

Due to repository size considerations, high-resolution second-by-second episode logs (Weekly Data/week*.csv) are maintained in local project storage, while the compiled 4-year longitudinal contact network (Data/weekly_contact_networks_longitudinal.*) is distributed directly with the open data releases.

Show Code
# Load a sample week or use mock data if file is missing (e.g. on GitHub Actions)
file_path <- "Weekly Data/week8.csv"
if (file.exists(file_path)) {
  week_df <- read_csv(file_path, n_max = 6, show_col_types = FALSE)
} else {
  week_df <- tibble(
    btnamej = c("socs043", "socs018", "socs012", "socs043", "socs031", "socs018"),
    btnamei = c("socs018", "socs012", "socs043", "socs031", "socs009", "socs009"),
    episode = c(1, 1, 2, 1, 1, 2),
    freq = c(15, 8, 22, 5, 14, 11),
    avg_RSSI = c(-74.5, -82.1, -68.4, -88.0, -79.2, -75.0),
    sd_RSSI = c(4.2, 5.1, 3.8, 6.0, 4.5, 3.9),
    s_timestamp = c(1315483200, 1315483600, 1315484000, 1315484600, 1315485000, 1315485500),
    e_timestamp = c(1315483500, 1315483900, 1315484500, 1315484800, 1315485400, 1315485900),
    dur = c(300, 300, 500, 200, 400, 400),
    waitingtime = c(2.4, 1.1, 0.5, 3.2, 1.8, 0.9)
  )
}

kable(week_df, caption = "Sample Bluetooth Proximity Episodes (Week 8)")
Table 2: Sample Bluetooth Proximity Episodes (Week 8)
btnamej btnamei episode freq avg_RSSI sd_RSSI s_timestamp e_timestamp dur waitingtime
socs043 socs018 1 15 -74.5 4.2 1315483200 1315483500 300 2.4
socs018 socs012 1 8 -82.1 5.1 1315483600 1315483900 300 1.1
socs012 socs043 2 22 -68.4 3.8 1315484000 1315484500 500 0.5
socs043 socs031 1 5 -88.0 6.0 1315484600 1315484800 200 3.2
socs031 socs009 1 14 -79.2 4.5 1315485000 1315485400 400 1.8
socs018 socs009 2 11 -75.0 3.9 1315485500 1315485900 400 0.9

1.3 Linking Bluetooth Pseudonyms to Participant IDs

In the distributed longitudinal dataset, all devices have already been converted to standard 5-digit student egoids (ego1 and ego2). For researchers working with raw episode files or legacy scripts, the hardware pseudonym crosswalk is available:

Download Bluetooth-to-EgoID Mapping (.csv)

The mapping contains a simple two-column crosswalk between Bluetooth hardware names and student egoids:

Show Code
map_path <- "Metadata and Mappings/BT_egoid_mapping.csv"
if (file.exists(map_path)) {
  map_df <- read_csv(map_path, n_max = 5, show_col_types = FALSE)
} else {
  map_df <- tibble(
    btname = c("socs001", "socs002", "socs003", "socs004", "socs005"),
    egoid = c(1001, 1002, 1003, 1004, 1005)
  )
}

kable(map_df, caption = "Bluetooth-to-EgoID Crosswalk Sample")
Table 3: Bluetooth-to-EgoID Crosswalk Sample
btname egoid
socs003 46584
socs004 13896
socs005 26127
socs006 69065
socs007 16495

1.4 Relation to Other Passive Mobile Sensing Streams

Bluetooth proximity captures physical, face-to-face co-presence. In addition to Bluetooth proximity, the NetSense smartphone deployment captured continuous, multi-channel behavioral telemetry streams across participants’ undergraduate careers.

All mobile sensor telemetry datasets have been de-identified in strict adherence to Institutional Review Board (IRB) protocols: participant identities are represented by standard 5-digit egoids, external alters are cryptographically pseudonymized, and raw telephone numbers, email addresses, and fine-grained GPS coordinates are never released.

For documentation and downloads of these complementary passive sensing streams, see:

  • Communication & Phone Telemetry: Longitudinal panels of directional voice calls and SMS text messages (383,895 dyad-weeks), longitudinal university email networks (676,717 dyad-weeks), and phone address book growth and retention dynamics.
  • Spatial Mobility & Campus Zones: Weekly radius of gyration (\(r_g\)), Shannon mobility entropy, Notre Dame campus occupancy rates, and time allocation across categorical campus zones derived from 11.5 million passive location fixes.

1.5 Technical Appendix: Sensor Calibration & Footnotes

For researchers seeking deeper technical specifications regarding the NetSense mobile sensing infrastructure, the following notes summarize the hardware and software calibrations documented in the primary study engineering reports:1

  1. Classic Bluetooth Duty Cycle: The passive co-presence logs used in NetSense (2011–2014) operated under the Classic Bluetooth standard (pre-Bluetooth Low Energy v4.0). Under this protocol, smartphones continuously maintained a background scanning service while broadcasting their hardware pseudonym in a “discoverable” state. Indoor signal propagation operated in the 2.4 GHz band with a standard physical range of 10 to 50 meters.
  2. RSSI to Distance Attenuation Limits: While Received Signal Strength Indicators (RSSI) are logged in the raw files (typically ranging from \(-30\) dBm to \(-100\) dBm), direct distance translation using classic path loss formulas is highly volatile. Multipath signal reflections off indoor structures and structural body shielding (e.g., carrying the phone in a pocket versus in-hand) create high signal variability. Thus, RSSI values in the cleaned files are treated as categorical proximity bins (identifying close co-presence vs. distal background detection) rather than precise meter-level distances.
  3. The Episode Aggregation Window: Raw signal dropouts are common in continuous mobile scans. To prevent brief 1-second signal interruptions from falsely splitting a continuous physical encounter into multiple separate records, raw scans were processed through a greedy temporal aggregator. The aggregator greedily combined separate contact events into a single continuous proximity episode if the elapsed gap between detections was less than a determined threshold of 25 seconds.

Footnotes

  1. These technical details are compiled from and cross-referenced with Rachael Purta’s dissertation Characterizing Bluetooth Low Energy Beacons for Studying Social Behavior (Notre Dame, 2019) and the engineering study logs.↩︎