ap = reticulate::py_require(c("actipy", "pyarrow"))
ap = reticulate::import("actipy")
library(tidyverse)
#> Warning: package 'ggplot2' was built under R version 4.4.3
#> Warning: package 'tibble' was built under R version 4.4.1
#> Warning: package 'tidyr' was built under R version 4.4.1
#> Warning: package 'purrr' was built under R version 4.4.3
#> Warning: package 'dplyr' was built under R version 4.4.3
#> Warning: package 'stringr' was built under R version 4.4.1
library(GGIRread)
#> Warning: package 'GGIRread' was built under R version 4.4.3
library(feather)
#> Warning: package 'feather' was built under R version 4.4.1
library(googledrive)
library(clock)
#>
#> Attaching package: 'clock'
#> The following object is masked from 'package:lubridate':
#>
#> as_date
options(digits.secs = 3L)
Read in CWA File
Example CWA file
This is the example data from the Axivity web page
zip_file = tempfile(fileext = ".zip")
url = "https://github.com/openmovementproject/openmovement/raw/refs/heads/master/Downloads/AX3/longitudinal_data.zip"
download.file(url, zip_file, mode = "wb")
file = unzip(zip_file, exdir = tempdir())
file
#> [1] "/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpTvLVc1/longitudinal_data.cwa"
CSV file from OMGUI
This is the data output from passing in the CWA to get a CSVfrom using OMGUI. This is the gold standard in the sense that Axivity lists it on the website as the software to use.
csv_file = tempfile(fileext = ".csv.gz")
csv_url = "https://www.dropbox.com/scl/fi/c03dkupyxlchept11gtwh/longitudinal_data.csv.gz?rlkey=njsm0bz36fzib7170t3uly4kp&dl=1"
curl::curl_download(csv_url, csv_file)
# This is the output to compare the output
om_gui_output = readr::read_csv(csv_file,
col_names = c("time", "x", "y", "z"))
#> Rows: 60337200 Columns: 4
#> ── Column specification ────────────────────────────────────────────────────────
#> Delimiter: ","
#> dbl (3): x, y, z
#> dttm (1): time
#>
#> ℹ Use `spec()` to retrieve the full column specification for this data.
#> ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
om_gui_output = om_gui_output |>
mutate(time = with_tz(time, Sys.timezone()))
Reading in CWA Data using GGIRread
Here is reading the data using GGIRread
r_list = readAxivity(file, end = Inf, progressBar = TRUE, desiredtz = "UTC", configtz = "UTC",
loadbattery = FALSE)
#> | | | 0% | | | 1% | |= | 1% | |= | 2% | |== | 2% | |== | 3% | |== | 4% | |=== | 4% | |=== | 5% | |==== | 5% | |==== | 6% | |===== | 6% | |===== | 7% | |===== | 8% | |====== | 8% | |====== | 9% | |======= | 9% | |======= | 10% | |======= | 11% | |======== | 11% | |======== | 12% | |========= | 12% | |========= | 13% | |========= | 14% | |========== | 14% | |========== | 15% | |=========== | 15% | |=========== | 16% | |============ | 16% | |============ | 17% | |============ | 18% | |============= | 18% | |============= | 19% | |============== | 19% | |============== | 20% | |============== | 21% | |=============== | 21% | |=============== | 22% | |================ | 22% | |================ | 23% | |================ | 24% | |================= | 24% | |================= | 25% | |================== | 25% | |================== | 26% | |=================== | 26% | |=================== | 27% | |=================== | 28% | |==================== | 28% | |==================== | 29% | |===================== | 29% | |===================== | 30% | |===================== | 31% | |====================== | 31% | |====================== | 32% | |======================= | 32% | |======================= | 33% | |======================= | 34% | |======================== | 34% | |======================== | 35% | |========================= | 35% | |========================= | 36% | |========================== | 36% | |========================== | 37% | |========================== | 38% | |=========================== | 38% | |=========================== | 39% | |============================ | 39% | |============================ | 40% | |============================ | 41% | |============================= | 41% | |============================= | 42% | |============================== | 42% | |============================== | 43% | |============================== | 44% | |=============================== | 44% | |=============================== | 45% | |================================ | 45% | |================================ | 46% | |================================= | 46% | |================================= | 47% | |================================= | 48% | |================================== | 48% | |================================== | 49% | |=================================== | 49% | |=================================== | 50% | |=================================== | 51% | |==================================== | 51% | |==================================== | 52% | |===================================== | 52% | |===================================== | 53% | |===================================== | 54% | |====================================== | 54% | |====================================== | 55% | |======================================= | 55% | |======================================= | 56% | |======================================== | 56% | |======================================== | 57% | |======================================== | 58% | |========================================= | 58% | |========================================= | 59% | |========================================== | 59% | |========================================== | 60% | |========================================== | 61% | |=========================================== | 61% | |=========================================== | 62% | |============================================ | 62% | |============================================ | 63% | |============================================ | 64% | |============================================= | 64% | |============================================= | 65% | |============================================== | 65% | |============================================== | 66% | |=============================================== | 66% | |=============================================== | 67% | |=============================================== | 68% | |================================================ | 68% | |================================================ | 69% | |================================================= | 69% | |================================================= | 70% | |================================================= | 71% | |================================================== | 71% | |================================================== | 72% | |=================================================== | 72% | |=================================================== | 73% | |=================================================== | 74% | |==================================================== | 74% | |==================================================== | 75% | |===================================================== | 75% | |===================================================== | 76% | |====================================================== | 76% | |====================================================== | 77% | |====================================================== | 78% | |======================================================= | 78% | |======================================================= | 79% | |======================================================== | 79% | |======================================================== | 80% | |======================================================== | 81% | |========================================================= | 81% | |========================================================= | 82% | |========================================================== | 82% | |========================================================== | 83% | |========================================================== | 84% | |=========================================================== | 84% | |=========================================================== | 85% | |============================================================ | 85% | |============================================================ | 86% | |============================================================= | 86% | |============================================================= | 87% | |============================================================= | 88% | |============================================================== | 88% | |============================================================== | 89% | |=============================================================== | 89% | |=============================================================== | 90% | |=============================================================== | 91% | |================================================================ | 91% | |================================================================ | 92% | |================================================================= | 92% | |================================================================= | 93% | |================================================================= | 94% | |================================================================== | 94% | |================================================================== | 95% | |=================================================================== | 95% | |=================================================================== | 96% | |==================================================================== | 96% | |==================================================================== | 97% | |==================================================================== | 98% | |===================================================================== | 98% | |===================================================================== | 99% | |======================================================================| 99% | |======================================================================| 100%
r_data = r_list$data |>
select(time, x, y, z)
r_data = r_data |>
mutate(time = as.POSIXct(time, tz = Sys.timezone()))
r_data = r_data |>
as_tibble()
Using actipy
Here we will use a call out to actipy from PyPi to compare to GGIRread
ap = reticulate::import("actipy", convert = FALSE)
Read in the device without processing
data = ap$read_device(
file,
lowpass_hz = FALSE,
calibrate_gravity = FALSE,
detect_nonwear = FALSE,
resample_hz = FALSE)
#> Reading file...Reading file... Done! (13.10s)
#> Converting to dataframe...Converting to dataframe... Done! (9.62s)
#> Quality control...Quality control... Done! (6.70s)
Grab the data
data = reticulate::py_get_item(data, 0L)
Here, instead of converting from Python to R, we can use feather as an intermediary because DateTimeIndex from pandas has some conversion issues in reticulate.
tfile = tempfile(fileext = ".feather")
data$to_feather(tfile)
#> None
rm(data); gc()
#> used (Mb) gc trigger (Mb) limit (Mb) max used (Mb)
#> Ncells 2711388 144.9 4819517 257.4 NA 4819517 257.4
#> Vcells 666834440 5087.6 1386603308 10579.0 65536 1147693973 8756.3
data = feather::read_feather(tfile)
file.remove(tfile)
#> [1] TRUE
tz(data$time) = Sys.timezone()
# time goes first
data = data |>
dplyr::select(time, x, y, z)
Checking results
Comparing actipy and OMGUI
all.equal(om_gui_output, data)
#> [1] TRUE
Comparing GGIRread and OMGUI
all.equal(om_gui_output, r_data)
#> [1] "Attributes: < Component \"row.names\": Numeric: lengths (60337200, 60110386) differ >"
#> [2] "Component \"time\": Numeric: lengths (60337200, 60110386) differ"
#> [3] "Component \"x\": Numeric: lengths (60337200, 60110386) differ"
#> [4] "Component \"y\": Numeric: lengths (60337200, 60110386) differ"
#> [5] "Component \"z\": Numeric: lengths (60337200, 60110386) differ"
Reading in actipy with uniform resampling
udata = ap$read_device(
file,
lowpass_hz = FALSE,
calibrate_gravity = FALSE,
detect_nonwear = FALSE,
resample_hz = "uniform")
#> Reading file...Reading file... Done! (11.96s)
#> Converting to dataframe...Converting to dataframe... Done! (9.42s)
#> Quality control...Quality control... Done! (6.67s)
#> Resampling...Resampling... Done! (22.06s)
Grab the data
udata = reticulate::py_get_item(udata, 0L)
tfile = tempfile(fileext = ".feather")
udata$to_feather(tfile)
#> None
rm(udata); gc()
#> used (Mb) gc trigger (Mb) limit (Mb) max used (Mb)
#> Ncells 2784592 148.8 4819517 257.4 NA 4819517 257.4
#> Vcells 908316718 6930.0 1386603308 10579.0 65536 1374681881 10488.0
udata = feather::read_feather(tfile)
file.remove(tfile)
#> [1] TRUE
tz(udata$time) = Sys.timezone()
# time goes first
udata = udata |>
dplyr::select(time, x, y, z)
Comparing Data Features
We can see the comparison, but future comparisons are only relevant for data and r_data since data == om_gui_output.
nrow(r_data)
#> [1] 60110386
nrow(data)
#> [1] 60337200
nrow(om_gui_output)
#> [1] 60337200
The sizes of the data are very different. This is because GGIRread does resampling for each block as per
|
tmp = resample(rawAccel, rawTime, timeRes[pos:last], rawLast, type = interpolationType) |
We can see the GGIRread output is similar in size to the uniform resampled data.
nrow(r_data)
#> [1] 60110386
nrow(udata)
#> [1] 60110388
The time covered is the same (data is in EST local for me, to keep things the same):
range(data$time)
#> [1] "2013-02-19 08:00:04.28 EST" "2013-02-26 06:58:28.16 EST"
range(r_data$time)
#> [1] "2013-02-19 08:00:04.28 EST" "2013-02-26 06:58:28.13 EST"
range(udata$time)
#> [1] "2013-02-19 08:00:04.28 EST" "2013-02-26 06:58:28.16 EST"
We see some small differences at the head of the data
head(data)
#> # A tibble: 6 × 4
#> time x y z
#> <dttm> <dbl> <dbl> <dbl>
#> 1 2013-02-19 08:00:04.289 0.0625 -0.0469 -0.922
#> 2 2013-02-19 08:00:04.299 -0.969 -0.0469 0.0469
#> 3 2013-02-19 08:00:04.310 -1.02 -0.0469 0.0469
#> 4 2013-02-19 08:00:04.319 -1.03 -0.0469 0.0469
#> 5 2013-02-19 08:00:04.329 -1.03 -0.0469 0.0469
#> 6 2013-02-19 08:00:04.339 -1.03 -0.0469 0.0469
head(r_data)
#> # A tibble: 6 × 4
#> time x y z
#> <dttm> <dbl> <dbl> <dbl>
#> 1 2013-02-19 08:00:04.289 0.0625 -0.0469 -0.922
#> 2 2013-02-19 08:00:04.299 -0.969 -0.0469 0.0469
#> 3 2013-02-19 08:00:04.309 -1.02 -0.0469 0.0469
#> 4 2013-02-19 08:00:04.319 -1.03 -0.0469 0.0469
#> 5 2013-02-19 08:00:04.329 -1.03 -0.0469 0.0469
#> 6 2013-02-19 08:00:04.339 -1.03 -0.0469 0.0462
head(udata)
#> # A tibble: 6 × 4
#> time x y z
#> <dttm> <dbl> <dbl> <dbl>
#> 1 2013-02-19 08:00:04.289 0.0625 -0.0469 -0.922
#> 2 2013-02-19 08:00:04.299 -0.969 -0.0469 0.0469
#> 3 2013-02-19 08:00:04.310 -1.02 -0.0469 0.0469
#> 4 2013-02-19 08:00:04.319 -1.03 -0.0469 0.0469
#> 5 2013-02-19 08:00:04.329 -1.03 -0.0469 0.0469
#> 6 2013-02-19 08:00:04.339 -1.03 -0.0469 0.0469
We see more differences towards the tail of the data, but time is somewhat mis-aligned
tail(data)
#> # A tibble: 6 × 4
#> time x y z
#> <dttm> <dbl> <dbl> <dbl>
#> 1 2013-02-26 06:58:28.110 -0.0156 -0.0156 -0.984
#> 2 2013-02-26 06:58:28.119 -0.0156 -0.0156 -0.984
#> 3 2013-02-26 06:58:28.129 -0.0156 -0.0156 -0.984
#> 4 2013-02-26 06:58:28.140 -0.0156 -0.0156 -0.969
#> 5 2013-02-26 06:58:28.150 -0.0156 -0.0312 -0.969
#> 6 2013-02-26 06:58:28.160 -0.0156 -0.0312 -0.984
tail(r_data)
#> # A tibble: 6 × 4
#> time x y z
#> <dttm> <dbl> <dbl> <dbl>
#> 1 2013-02-26 06:58:28.089 -0.0156 -0.0156 -0.977
#> 2 2013-02-26 06:58:28.099 -0.0156 -0.0156 -0.969
#> 3 2013-02-26 06:58:28.109 -0.0156 -0.0231 -0.969
#> 4 2013-02-26 06:58:28.119 -0.0156 -0.0310 -0.969
#> 5 2013-02-26 06:58:28.129 -0.0156 -0.0312 -0.976
#> 6 2013-02-26 06:58:28.139 -0.0156 -0.0312 -0.984
tail(udata)
#> # A tibble: 6 × 4
#> time x y z
#> <dttm> <dbl> <dbl> <dbl>
#> 1 2013-02-26 06:58:28.110 -0.0156 -0.0156 -0.984
#> 2 2013-02-26 06:58:28.119 -0.0156 -0.0156 -0.984
#> 3 2013-02-26 06:58:28.129 -0.0156 -0.0156 -0.984
#> 4 2013-02-26 06:58:28.140 -0.0156 -0.0156 -0.969
#> 5 2013-02-26 06:58:28.150 -0.0156 -0.0312 -0.969
#> 6 2013-02-26 06:58:28.160 -0.0156 -0.0312 -0.984
We see differences in the data, but it's unclear how this affects downstream analysis
keep_cols = c("time", "x", "y", "z")
data[3714:3720, keep_cols]
#> # A tibble: 7 × 4
#> time x y z
#> <dttm> <dbl> <dbl> <dbl>
#> 1 2013-02-19 08:00:41.230 -0.703 -0.109 -0.359
#> 2 2013-02-19 08:00:41.240 -0.703 -0.0938 -0.406
#> 3 2013-02-19 08:00:41.249 -0.734 -0.0625 -0.5
#> 4 2013-02-19 08:00:41.259 -0.781 -0.0156 -0.562
#> 5 2013-02-19 08:00:41.270 -0.828 0.0469 -0.484
#> 6 2013-02-19 08:00:41.279 -0.875 0.0781 -0.422
#> 7 2013-02-19 08:00:41.289 -0.953 0.109 -0.344
r_data[3695:3701, keep_cols]
#> # A tibble: 7 × 4
#> time x y z
#> <dttm> <dbl> <dbl> <dbl>
#> 1 2013-02-19 08:00:41.230 -0.703 -0.0945 -0.404
#> 2 2013-02-19 08:00:41.240 -0.733 -0.0638 -0.496
#> 3 2013-02-19 08:00:41.250 -0.780 -0.0172 -0.560
#> 4 2013-02-19 08:00:41.259 -0.827 0.0453 -0.486
#> 5 2013-02-19 08:00:41.269 -0.874 0.0776 -0.423
#> 6 2013-02-19 08:00:41.279 -0.952 0.109 -0.344
#> 7 2013-02-19 08:00:41.289 -0.969 0.109 -0.281
udata[3695:3701, keep_cols]
#> # A tibble: 7 × 4
#> time x y z
#> <dttm> <dbl> <dbl> <dbl>
#> 1 2013-02-19 08:00:41.230 -0.703 -0.109 -0.359
#> 2 2013-02-19 08:00:41.240 -0.703 -0.0938 -0.406
#> 3 2013-02-19 08:00:41.249 -0.734 -0.0625 -0.5
#> 4 2013-02-19 08:00:41.259 -0.781 -0.0156 -0.562
#> 5 2013-02-19 08:00:41.270 -0.828 0.0469 -0.484
#> 6 2013-02-19 08:00:41.279 -0.875 0.0781 -0.422
#> 7 2013-02-19 08:00:41.289 -0.953 0.109 -0.344
r_data[3695:3701,keep_cols]- data[3714:3720,keep_cols]
#> time x y z
#> 1 0.000000e+00 secs 0.00000000 0.01483725 -0.04451175
#> 2 0.000000e+00 secs -0.02993743 0.02993743 -0.08981229
#> 3 2.384186e-07 secs -0.04529950 0.04529950 -0.06039934
#> 4 0.000000e+00 secs -0.04569391 0.06092522 0.07615652
#> 5 -2.384186e-07 secs -0.04608725 0.03072483 0.06144967
#> 6 0.000000e+00 secs -0.07746947 0.03098779 0.07746947
#> 7 0.000000e+00 secs -0.01562500 0.00000000 0.06250000
actipy resampling can be odd
If we look at the uniform sampling output of actipy, we can see some odd values of 0:
tail(udata, n = 20)
#> # A tibble: 20 × 4
#> time x y z
#> <dttm> <dbl> <dbl> <dbl>
#> 1 2013-02-26 06:58:27.969 0 0 -0.969
#> 2 2013-02-26 06:58:27.980 0.0156 -0.0312 -0.969
#> 3 2013-02-26 06:58:27.990 0 -0.0156 -0.984
#> 4 2013-02-26 06:58:28.000 -0.0312 0 -0.984
#> 5 2013-02-26 06:58:28.009 -0.0156 0 -0.969
#> 6 2013-02-26 06:58:28.019 -0.0156 0 -0.969
#> 7 2013-02-26 06:58:28.030 -0.0156 -0.0156 -0.984
#> 8 2013-02-26 06:58:28.039 0 -0.0156 -0.984
#> 9 2013-02-26 06:58:28.049 -0.0156 -0.0156 -0.984
#> 10 2013-02-26 06:58:28.059 -0.0156 -0.0156 -0.984
#> 11 2013-02-26 06:58:28.070 -0.0312 0 -0.969
#> 12 2013-02-26 06:58:28.079 -0.0156 -0.0156 -0.969
#> 13 2013-02-26 06:58:28.089 -0.0156 -0.0156 -0.984
#> 14 2013-02-26 06:58:28.099 -0.0156 -0.0156 -0.984
#> 15 2013-02-26 06:58:28.110 -0.0156 -0.0156 -0.984
#> 16 2013-02-26 06:58:28.119 -0.0156 -0.0156 -0.984
#> 17 2013-02-26 06:58:28.129 -0.0156 -0.0156 -0.984
#> 18 2013-02-26 06:58:28.140 -0.0156 -0.0156 -0.969
#> 19 2013-02-26 06:58:28.150 -0.0156 -0.0312 -0.969
#> 20 2013-02-26 06:58:28.160 -0.0156 -0.0312 -0.984
We do not see these issues similarly in GGIRread output
tail(r_data, n = 18)
#> # A tibble: 18 × 4
#> time x y z
#> <dttm> <dbl> <dbl> <dbl>
#> 1 2013-02-26 06:58:27.970 -0.0247 -0.00657 -0.969
#> 2 2013-02-26 06:58:27.980 -0.0168 -0.0144 -0.969
#> 3 2013-02-26 06:58:27.990 -0.0156 -0.0156 -0.975
#> 4 2013-02-26 06:58:28.000 -0.0156 -0.0156 -0.983
#> 5 2013-02-26 06:58:28.009 -0.0156 -0.0156 -0.984
#> 6 2013-02-26 06:58:28.019 -0.0156 -0.0156 -0.984
#> 7 2013-02-26 06:58:28.029 -0.0156 -0.0156 -0.984
#> 8 2013-02-26 06:58:28.039 -0.0156 -0.0156 -0.984
#> 9 2013-02-26 06:58:28.049 -0.0156 -0.0156 -0.984
#> 10 2013-02-26 06:58:28.059 -0.0156 -0.0156 -0.984
#> 11 2013-02-26 06:58:28.069 -0.0156 -0.0156 -0.984
#> 12 2013-02-26 06:58:28.079 -0.0156 -0.0156 -0.984
#> 13 2013-02-26 06:58:28.089 -0.0156 -0.0156 -0.977
#> 14 2013-02-26 06:58:28.099 -0.0156 -0.0156 -0.969
#> 15 2013-02-26 06:58:28.109 -0.0156 -0.0231 -0.969
#> 16 2013-02-26 06:58:28.119 -0.0156 -0.0310 -0.969
#> 17 2013-02-26 06:58:28.129 -0.0156 -0.0312 -0.976
#> 18 2013-02-26 06:58:28.139 -0.0156 -0.0312 -0.984
Conclusion
If users are aiming to replicate the output from OMGUI, GGIRread will not give it, but actipy can, but the data should likely be resampled. I’m not sure how this affects downstream analysis overall. The actipy uniform resampling has its own issues. If possible, maybe allow users to get the raw data out and do resampling on their own.
df = reticulate::py_list_packages()
df$version[df$package == "actipy"]
#> [1] "3.8.0"
Created on 2026-06-23 with reprex v2.1.1
Session info
sessioninfo::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#> setting value
#> version R version 4.4.0 (2024-04-24)
#> os macOS 26.5.1
#> system x86_64, darwin20
#> ui X11
#> language (EN)
#> collate en_US.UTF-8
#> ctype en_US.UTF-8
#> tz America/New_York
#> date 2026-06-23
#> pandoc 3.8.3 @ /Applications/RStudio.app/Contents/Resources/app/quarto/bin/tools/x86_64/ (via rmarkdown)
#>
#> ─ Packages ───────────────────────────────────────────────────────────────────
#> package * version date (UTC) lib source
#> arrow 18.1.0.1 2025-01-08 [1] CRAN (R 4.4.1)
#> assertthat 0.2.1 2019-03-21 [1] CRAN (R 4.4.0)
#> bit 4.6.0 2025-03-06 [1] CRAN (R 4.4.1)
#> bit64 4.8.2 2026-05-19 [1] CRAN (R 4.4.3)
#> cli 3.6.6 2026-04-09 [1] CRAN (R 4.4.3)
#> clock * 0.7.1 2024-07-18 [1] CRAN (R 4.4.0)
#> crayon 1.5.3 2024-06-20 [1] CRAN (R 4.4.0)
#> curl 7.1.0 2026-04-22 [1] CRAN (R 4.4.3)
#> data.table 1.18.4 2026-05-06 [1] CRAN (R 4.4.3)
#> dichromat 2.0-0.1 2022-05-02 [1] CRAN (R 4.4.0)
#> digest 0.6.39 2025-11-19 [1] CRAN (R 4.4.1)
#> dplyr * 1.2.1 2026-04-03 [1] CRAN (R 4.4.3)
#> evaluate 1.0.5 2025-08-27 [1] CRAN (R 4.4.1)
#> farver 2.1.2 2024-05-13 [1] CRAN (R 4.4.0)
#> fastmap 1.2.0 2024-05-15 [1] CRAN (R 4.4.0)
#> feather * 0.4.0 2025-12-06 [1] CRAN (R 4.4.1)
#> forcats * 1.0.0 2023-01-29 [1] CRAN (R 4.4.0)
#> fs 2.1.0 2026-04-18 [1] CRAN (R 4.4.3)
#> gargle 1.5.2 2023-07-20 [1] CRAN (R 4.4.0)
#> generics 0.1.4 2025-05-09 [1] CRAN (R 4.4.1)
#> GGIRread * 1.0.8 2026-03-11 [1] CRAN (R 4.4.3)
#> ggplot2 * 4.0.3 2026-04-22 [1] CRAN (R 4.4.3)
#> glue 1.8.1 2026-04-17 [1] CRAN (R 4.4.3)
#> googledrive * 2.1.1 2023-06-11 [1] CRAN (R 4.4.0)
#> gtable 0.3.6 2024-10-25 [1] CRAN (R 4.4.1)
#> hms 1.1.4 2025-10-17 [1] CRAN (R 4.4.1)
#> htmltools 0.5.9 2025-12-04 [1] CRAN (R 4.4.1)
#> jsonlite 2.0.0 2025-03-27 [1] CRAN (R 4.4.1)
#> knitr 1.51 2025-12-20 [1] CRAN (R 4.4.1)
#> lattice 0.22-6 2024-03-20 [1] CRAN (R 4.4.0)
#> lifecycle 1.0.5 2026-01-08 [1] CRAN (R 4.4.1)
#> lubridate * 1.9.5.9000 2026-06-17 [1] Github (tidyverse/lubridate@8e9f2b2)
#> magrittr 2.0.5 2026-04-04 [1] CRAN (R 4.4.3)
#> Matrix 1.7-2 2025-01-23 [1] CRAN (R 4.4.1)
#> otel 0.2.0 2025-08-29 [1] CRAN (R 4.4.1)
#> pillar 1.11.1 2025-09-17 [1] CRAN (R 4.4.1)
#> pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 4.4.0)
#> png 0.1-9 2026-03-15 [1] CRAN (R 4.4.3)
#> purrr * 1.2.2 2026-04-10 [1] CRAN (R 4.4.3)
#> R6 2.6.1 2025-02-15 [1] CRAN (R 4.4.1)
#> RColorBrewer 1.1-3 2022-04-03 [1] CRAN (R 4.4.0)
#> Rcpp 1.1.1-1.1 2026-04-24 [1] CRAN (R 4.4.3)
#> readr * 2.1.5 2024-01-10 [1] CRAN (R 4.4.0)
#> reprex 2.1.1 2024-07-06 [1] CRAN (R 4.4.0)
#> reticulate 1.46.0 2026-04-09 [1] CRAN (R 4.4.3)
#> rlang 1.2.0 2026-04-06 [1] CRAN (R 4.4.3)
#> rmarkdown 2.31 2026-03-26 [1] CRAN (R 4.4.3)
#> rstudioapi 0.18.0 2026-01-16 [1] CRAN (R 4.4.1)
#> S7 0.2.2 2026-04-22 [1] CRAN (R 4.4.3)
#> scales 1.4.0 2025-04-24 [1] CRAN (R 4.4.1)
#> sessioninfo 1.2.2 2021-12-06 [1] CRAN (R 4.4.0)
#> stringi 1.8.7 2025-03-27 [1] CRAN (R 4.4.1)
#> stringr * 1.6.0 2025-11-04 [1] CRAN (R 4.4.1)
#> tibble * 3.3.1 2026-01-11 [1] CRAN (R 4.4.1)
#> tidyr * 1.3.2 2025-12-19 [1] CRAN (R 4.4.1)
#> tidyselect 1.2.1 2024-03-11 [1] CRAN (R 4.4.0)
#> tidyverse * 2.0.0 2023-02-22 [1] CRAN (R 4.4.0)
#> timechange 0.4.0 2026-01-29 [1] CRAN (R 4.4.1)
#> tzdb 0.5.0 2025-03-15 [1] CRAN (R 4.4.1)
#> vctrs 0.7.3.9000 2026-05-11 [1] Github (r-lib/vctrs@b5c0894)
#> vroom 1.7.1 2026-03-31 [1] CRAN (R 4.4.3)
#> withr 3.0.2 2024-10-28 [1] CRAN (R 4.4.1)
#> xfun 0.57 2026-03-20 [1] CRAN (R 4.4.3)
#> yaml 2.3.12 2025-12-10 [1] CRAN (R 4.4.1)
#>
#> [1] /Library/Frameworks/R.framework/Versions/4.4-x86_64/Resources/library
#>
#> ─ Python configuration ───────────────────────────────────────────────────────
#> python: /Users/johnmuschelli/Library/Caches/org.R-project.R/R/reticulate/uv/cache/archive-v0/neF1dAcvz5AdiF3V/bin/python
#> libpython: /Users/johnmuschelli/Library/Caches/org.R-project.R/R/reticulate/uv/python/cpython-3.12.13-macos-x86_64-none/lib/libpython3.12.dylib
#> pythonhome: /Users/johnmuschelli/Library/Caches/org.R-project.R/R/reticulate/uv/cache/archive-v0/neF1dAcvz5AdiF3V:/Users/johnmuschelli/Library/Caches/org.R-project.R/R/reticulate/uv/cache/archive-v0/neF1dAcvz5AdiF3V
#> virtualenv: /Users/johnmuschelli/Library/Caches/org.R-project.R/R/reticulate/uv/cache/archive-v0/neF1dAcvz5AdiF3V/bin/activate_this.py
#> version: 3.12.13 (main, May 10 2026, 19:20:48) [Clang 22.1.3 ]
#> numpy: /Users/johnmuschelli/Library/Caches/org.R-project.R/R/reticulate/uv/cache/archive-v0/neF1dAcvz5AdiF3V/lib/python3.12/site-packages/numpy
#> numpy_version: 2.5.0
#> actipy: /Users/johnmuschelli/Library/Caches/org.R-project.R/R/reticulate/uv/cache/archive-v0/neF1dAcvz5AdiF3V/lib/python3.12/site-packages/actipy
#>
#> NOTE: Python version was forced by py_require()
#>
#> ──────────────────────────────────────────────────────────────────────────────
Read in CWA File
Example CWA file
This is the example data from the Axivity web page
CSV file from OMGUI
This is the data output from passing in the CWA to get a CSVfrom using OMGUI. This is the gold standard in the sense that Axivity lists it on the website as the software to use.
Reading in CWA Data using GGIRread
Here is reading the data using GGIRread
Using
actipyHere we will use a call out to actipy from PyPi to compare to GGIRread
Read in the device without processing
Grab the data
Here, instead of converting from Python to R, we can use feather as an intermediary because DateTimeIndex from
pandashas some conversion issues inreticulate.Checking results
Comparing
actipyand OMGUIComparing
GGIRreadand OMGUIReading in
actipywith uniform resamplingGrab the data
Comparing Data Features
We can see the comparison, but future comparisons are only relevant for
dataandr_datasincedata==om_gui_output.The sizes of the data are very different. This is because
GGIRreaddoes resampling for each block as perGGIRread/R/readAxivity.R
Line 655 in 302919a
We can see the GGIRread output is similar in size to the uniform resampled data.
The time covered is the same (data is in EST local for me, to keep things the same):
We see some small differences at the head of the data
We see more differences towards the tail of the data, but time is somewhat mis-aligned
We see differences in the data, but it's unclear how this affects downstream analysis
actipyresampling can be oddIf we look at the uniform sampling output of
actipy, we can see some odd values of0:We do not see these issues similarly in
GGIRreadoutputConclusion
If users are aiming to replicate the output from OMGUI,
GGIRreadwill not give it, butactipycan, but the data should likely be resampled. I’m not sure how this affects downstream analysis overall. Theactipyuniform resampling has its own issues. If possible, maybe allow users to get the raw data out and do resampling on their own.Created on 2026-06-23 with reprex v2.1.1
Session info