mirror of
https://github.com/agdamsbo/REDCapCAST.git
synced 2026-06-19 13:17:30 +02:00
Compare commits
No commits in common. "db75c3313e8d864bd6db7a89866910e55cc12bb4" and "965aa310ca2a53b6159051675c2922f1682678f2" have entirely different histories.
db75c3313e
...
965aa310ca
7 changed files with 833 additions and 3291 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
Package: REDCapCAST
|
Package: REDCapCAST
|
||||||
Title: REDCap Metadata Casting and Castellated Data Handling
|
Title: REDCap Metadata Casting and Castellated Data Handling
|
||||||
Version: 25.11.1
|
Version: 25.3.2
|
||||||
Authors@R: c(
|
Authors@R: c(
|
||||||
person("Andreas Gammelgaard", "Damsbo", email = "agdamsbo@clin.au.dk",
|
person("Andreas Gammelgaard", "Damsbo", email = "agdamsbo@clin.au.dk",
|
||||||
role = c("aut", "cre"),comment = c(ORCID = "0000-0002-7559-1154")),
|
role = c("aut", "cre"),comment = c(ORCID = "0000-0002-7559-1154")),
|
||||||
|
|
|
||||||
6
NEWS.md
6
NEWS.md
|
|
@ -1,9 +1,3 @@
|
||||||
# REDCapCAST 25.11.1
|
|
||||||
|
|
||||||
* FIX: logiccals exported as numeric for data upload
|
|
||||||
|
|
||||||
* FIX: improved name cleaning
|
|
||||||
|
|
||||||
# REDCapCAST 25.3.2
|
# REDCapCAST 25.3.2
|
||||||
|
|
||||||
* BUG: The `redcap_wider()` function would attempt to pivot empty selection of columns from list, and failing, causing all functions relying on this to fail. Fixed by filtering out data.frames in list with no additional columns than the "generics".
|
* BUG: The `redcap_wider()` function would attempt to pivot empty selection of columns from list, and failing, causing all functions relying on this to fail. Fixed by filtering out data.frames in list with no additional columns than the "generics".
|
||||||
|
|
|
||||||
|
|
@ -446,7 +446,7 @@ ds2dd_detailed <- function(data,
|
||||||
hms2character() |>
|
hms2character() |>
|
||||||
stats::setNames(dd$field_name) |>
|
stats::setNames(dd$field_name) |>
|
||||||
lapply(\(.x){
|
lapply(\(.x){
|
||||||
if (identical("factor", class(.x)) | identical("logical", class(.x))) {
|
if (identical("factor", class(.x))) {
|
||||||
as.numeric(.x)
|
as.numeric(.x)
|
||||||
} else {
|
} else {
|
||||||
.x
|
.x
|
||||||
|
|
|
||||||
19
R/utils.r
19
R/utils.r
|
|
@ -99,18 +99,10 @@ focused_metadata <- function(metadata, vars_in_data) {
|
||||||
#'
|
#'
|
||||||
#' @examples
|
#' @examples
|
||||||
#' "Research!, ne:ws? and c;l-.ls" |> clean_redcap_name()
|
#' "Research!, ne:ws? and c;l-.ls" |> clean_redcap_name()
|
||||||
#' "8_new_TEST_" |> clean_redcap_name()
|
|
||||||
clean_redcap_name <- function(x) {
|
clean_redcap_name <- function(x) {
|
||||||
gsub(
|
gsub("[,.;:?!@]","",
|
||||||
"[,.;:?!@]", "",
|
|
||||||
gsub(
|
gsub(
|
||||||
" ", "_",
|
" ", "_",
|
||||||
gsub(
|
|
||||||
"__", "_",
|
|
||||||
gsub(
|
|
||||||
"*_$", "",
|
|
||||||
gsub(
|
|
||||||
"^_*", "",
|
|
||||||
gsub(
|
gsub(
|
||||||
"[' ']$", "",
|
"[' ']$", "",
|
||||||
gsub(
|
gsub(
|
||||||
|
|
@ -120,9 +112,6 @@ clean_redcap_name <- function(x) {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -368,10 +357,8 @@ split_non_repeating_forms <-
|
||||||
#' @export
|
#' @export
|
||||||
#'
|
#'
|
||||||
#' @examples
|
#' @examples
|
||||||
#' test <- c(
|
#' test <- c("12 months follow-up", "3 steps", "mRS 6 weeks",
|
||||||
#' "12 months follow-up", "3 steps", "mRS 6 weeks",
|
#' "Counting to 231 now")
|
||||||
#' "Counting to 231 now"
|
|
||||||
#' )
|
|
||||||
#' strsplitx(test, "[0-9]", type = "around")
|
#' strsplitx(test, "[0-9]", type = "around")
|
||||||
strsplitx <- function(x,
|
strsplitx <- function(x,
|
||||||
split,
|
split,
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,6 @@ account: agdamsbo
|
||||||
server: shinyapps.io
|
server: shinyapps.io
|
||||||
hostUrl: https://api.shinyapps.io/v1
|
hostUrl: https://api.shinyapps.io/v1
|
||||||
appId: 11351429
|
appId: 11351429
|
||||||
bundleId:
|
bundleId: 9642648
|
||||||
url: https://agdamsbo.shinyapps.io/redcapcast/
|
url: https://agdamsbo.shinyapps.io/redcapcast/
|
||||||
version: 1
|
version: 1
|
||||||
|
|
|
||||||
3756
renv.lock
3756
renv.lock
File diff suppressed because one or more lines are too long
229
renv/activate.R
229
renv/activate.R
|
|
@ -2,7 +2,7 @@
|
||||||
local({
|
local({
|
||||||
|
|
||||||
# the requested version of renv
|
# the requested version of renv
|
||||||
version <- "1.1.5"
|
version <- "1.0.11"
|
||||||
attr(version, "sha") <- NULL
|
attr(version, "sha") <- NULL
|
||||||
|
|
||||||
# the project directory
|
# the project directory
|
||||||
|
|
@ -42,7 +42,7 @@ local({
|
||||||
return(FALSE)
|
return(FALSE)
|
||||||
|
|
||||||
# next, check environment variables
|
# next, check environment variables
|
||||||
# prefer using the configuration one in the future
|
# TODO: prefer using the configuration one in the future
|
||||||
envvars <- c(
|
envvars <- c(
|
||||||
"RENV_CONFIG_AUTOLOADER_ENABLED",
|
"RENV_CONFIG_AUTOLOADER_ENABLED",
|
||||||
"RENV_AUTOLOADER_ENABLED",
|
"RENV_AUTOLOADER_ENABLED",
|
||||||
|
|
@ -135,12 +135,12 @@ local({
|
||||||
|
|
||||||
# R help links
|
# R help links
|
||||||
pattern <- "`\\?(renv::(?:[^`])+)`"
|
pattern <- "`\\?(renv::(?:[^`])+)`"
|
||||||
replacement <- "`\033]8;;x-r-help:\\1\a?\\1\033]8;;\a`"
|
replacement <- "`\033]8;;ide:help:\\1\a?\\1\033]8;;\a`"
|
||||||
text <- gsub(pattern, replacement, text, perl = TRUE)
|
text <- gsub(pattern, replacement, text, perl = TRUE)
|
||||||
|
|
||||||
# runnable code
|
# runnable code
|
||||||
pattern <- "`(renv::(?:[^`])+)`"
|
pattern <- "`(renv::(?:[^`])+)`"
|
||||||
replacement <- "`\033]8;;x-r-run:\\1\a\\1\033]8;;\a`"
|
replacement <- "`\033]8;;ide:run:\\1\a\\1\033]8;;\a`"
|
||||||
text <- gsub(pattern, replacement, text, perl = TRUE)
|
text <- gsub(pattern, replacement, text, perl = TRUE)
|
||||||
|
|
||||||
# return ansified text
|
# return ansified text
|
||||||
|
|
@ -209,6 +209,10 @@ local({
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startswith <- function(string, prefix) {
|
||||||
|
substring(string, 1, nchar(prefix)) == prefix
|
||||||
|
}
|
||||||
|
|
||||||
bootstrap <- function(version, library) {
|
bootstrap <- function(version, library) {
|
||||||
|
|
||||||
friendly <- renv_bootstrap_version_friendly(version)
|
friendly <- renv_bootstrap_version_friendly(version)
|
||||||
|
|
@ -559,9 +563,6 @@ local({
|
||||||
|
|
||||||
# prepare download options
|
# prepare download options
|
||||||
token <- renv_bootstrap_github_token()
|
token <- renv_bootstrap_github_token()
|
||||||
if (is.null(token))
|
|
||||||
token <- ""
|
|
||||||
|
|
||||||
if (nzchar(Sys.which("curl")) && nzchar(token)) {
|
if (nzchar(Sys.which("curl")) && nzchar(token)) {
|
||||||
fmt <- "--location --fail --header \"Authorization: token %s\""
|
fmt <- "--location --fail --header \"Authorization: token %s\""
|
||||||
extra <- sprintf(fmt, token)
|
extra <- sprintf(fmt, token)
|
||||||
|
|
@ -695,19 +696,11 @@ local({
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renv_bootstrap_platform_prefix_default <- function() {
|
renv_bootstrap_platform_prefix <- function() {
|
||||||
|
|
||||||
# read version component
|
# construct version prefix
|
||||||
version <- Sys.getenv("RENV_PATHS_VERSION", unset = "R-%v")
|
version <- paste(R.version$major, R.version$minor, sep = ".")
|
||||||
|
prefix <- paste("R", numeric_version(version)[1, 1:2], sep = "-")
|
||||||
# expand placeholders
|
|
||||||
placeholders <- list(
|
|
||||||
list("%v", format(getRversion()[1, 1:2])),
|
|
||||||
list("%V", format(getRversion()[1, 1:3]))
|
|
||||||
)
|
|
||||||
|
|
||||||
for (placeholder in placeholders)
|
|
||||||
version <- gsub(placeholder[[1L]], placeholder[[2L]], version, fixed = TRUE)
|
|
||||||
|
|
||||||
# include SVN revision for development versions of R
|
# include SVN revision for development versions of R
|
||||||
# (to avoid sharing platform-specific artefacts with released versions of R)
|
# (to avoid sharing platform-specific artefacts with released versions of R)
|
||||||
|
|
@ -716,19 +709,10 @@ local({
|
||||||
identical(R.version[["nickname"]], "Unsuffered Consequences")
|
identical(R.version[["nickname"]], "Unsuffered Consequences")
|
||||||
|
|
||||||
if (devel)
|
if (devel)
|
||||||
version <- paste(version, R.version[["svn rev"]], sep = "-r")
|
prefix <- paste(prefix, R.version[["svn rev"]], sep = "-r")
|
||||||
|
|
||||||
version
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
renv_bootstrap_platform_prefix <- function() {
|
|
||||||
|
|
||||||
# construct version prefix
|
|
||||||
version <- renv_bootstrap_platform_prefix_default()
|
|
||||||
|
|
||||||
# build list of path components
|
# build list of path components
|
||||||
components <- c(version, R.version$platform)
|
components <- c(prefix, R.version$platform)
|
||||||
|
|
||||||
# include prefix if provided by user
|
# include prefix if provided by user
|
||||||
prefix <- renv_bootstrap_platform_prefix_impl()
|
prefix <- renv_bootstrap_platform_prefix_impl()
|
||||||
|
|
@ -967,14 +951,8 @@ local({
|
||||||
}
|
}
|
||||||
|
|
||||||
renv_bootstrap_validate_version_dev <- function(version, description) {
|
renv_bootstrap_validate_version_dev <- function(version, description) {
|
||||||
|
|
||||||
expected <- description[["RemoteSha"]]
|
expected <- description[["RemoteSha"]]
|
||||||
if (!is.character(expected))
|
is.character(expected) && startswith(expected, version)
|
||||||
return(FALSE)
|
|
||||||
|
|
||||||
pattern <- sprintf("^\\Q%s\\E", version)
|
|
||||||
grepl(pattern, expected, perl = TRUE)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renv_bootstrap_validate_version_release <- function(version, description) {
|
renv_bootstrap_validate_version_release <- function(version, description) {
|
||||||
|
|
@ -1154,10 +1132,10 @@ local({
|
||||||
|
|
||||||
renv_bootstrap_exec <- function(project, libpath, version) {
|
renv_bootstrap_exec <- function(project, libpath, version) {
|
||||||
if (!renv_bootstrap_load(project, libpath, version))
|
if (!renv_bootstrap_load(project, libpath, version))
|
||||||
renv_bootstrap_run(project, libpath, version)
|
renv_bootstrap_run(version, libpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
renv_bootstrap_run <- function(project, libpath, version) {
|
renv_bootstrap_run <- function(version, libpath) {
|
||||||
|
|
||||||
# perform bootstrap
|
# perform bootstrap
|
||||||
bootstrap(version, libpath)
|
bootstrap(version, libpath)
|
||||||
|
|
@ -1168,7 +1146,7 @@ local({
|
||||||
|
|
||||||
# try again to load
|
# try again to load
|
||||||
if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) {
|
if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) {
|
||||||
return(renv::load(project = project))
|
return(renv::load(project = getwd()))
|
||||||
}
|
}
|
||||||
|
|
||||||
# failed to download or load renv; warn the user
|
# failed to download or load renv; warn the user
|
||||||
|
|
@ -1214,105 +1192,98 @@ local({
|
||||||
jsonlite::fromJSON(txt = text, simplifyVector = FALSE)
|
jsonlite::fromJSON(txt = text, simplifyVector = FALSE)
|
||||||
}
|
}
|
||||||
|
|
||||||
renv_json_read_patterns <- function() {
|
|
||||||
|
|
||||||
list(
|
|
||||||
|
|
||||||
# objects
|
|
||||||
list("{", "\t\n\tobject(\t\n\t", TRUE),
|
|
||||||
list("}", "\t\n\t)\t\n\t", TRUE),
|
|
||||||
|
|
||||||
# arrays
|
|
||||||
list("[", "\t\n\tarray(\t\n\t", TRUE),
|
|
||||||
list("]", "\n\t\n)\n\t\n", TRUE),
|
|
||||||
|
|
||||||
# maps
|
|
||||||
list(":", "\t\n\t=\t\n\t", TRUE),
|
|
||||||
|
|
||||||
# newlines
|
|
||||||
list("\\u000a", "\n", FALSE)
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
renv_json_read_envir <- function() {
|
|
||||||
|
|
||||||
envir <- new.env(parent = emptyenv())
|
|
||||||
|
|
||||||
envir[["+"]] <- `+`
|
|
||||||
envir[["-"]] <- `-`
|
|
||||||
|
|
||||||
envir[["object"]] <- function(...) {
|
|
||||||
result <- list(...)
|
|
||||||
names(result) <- as.character(names(result))
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
envir[["array"]] <- list
|
|
||||||
|
|
||||||
envir[["true"]] <- TRUE
|
|
||||||
envir[["false"]] <- FALSE
|
|
||||||
envir[["null"]] <- NULL
|
|
||||||
|
|
||||||
envir
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
renv_json_read_remap <- function(object, patterns) {
|
|
||||||
|
|
||||||
# repair names if necessary
|
|
||||||
if (!is.null(names(object))) {
|
|
||||||
|
|
||||||
nms <- names(object)
|
|
||||||
for (pattern in patterns)
|
|
||||||
nms <- gsub(pattern[[2L]], pattern[[1L]], nms, fixed = TRUE)
|
|
||||||
names(object) <- nms
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
# repair strings if necessary
|
|
||||||
if (is.character(object)) {
|
|
||||||
for (pattern in patterns)
|
|
||||||
object <- gsub(pattern[[2L]], pattern[[1L]], object, fixed = TRUE)
|
|
||||||
}
|
|
||||||
|
|
||||||
# recurse for other objects
|
|
||||||
if (is.recursive(object))
|
|
||||||
for (i in seq_along(object))
|
|
||||||
object[i] <- list(renv_json_read_remap(object[[i]], patterns))
|
|
||||||
|
|
||||||
# return remapped object
|
|
||||||
object
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
renv_json_read_default <- function(file = NULL, text = NULL) {
|
renv_json_read_default <- function(file = NULL, text = NULL) {
|
||||||
|
|
||||||
# read json text
|
# find strings in the JSON
|
||||||
text <- paste(text %||% readLines(file, warn = FALSE), collapse = "\n")
|
text <- paste(text %||% readLines(file, warn = FALSE), collapse = "\n")
|
||||||
|
pattern <- '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||||
|
locs <- gregexpr(pattern, text, perl = TRUE)[[1]]
|
||||||
|
|
||||||
# convert into something the R parser will understand
|
# if any are found, replace them with placeholders
|
||||||
patterns <- renv_json_read_patterns()
|
replaced <- text
|
||||||
transformed <- text
|
strings <- character()
|
||||||
for (pattern in patterns)
|
replacements <- character()
|
||||||
transformed <- gsub(pattern[[1L]], pattern[[2L]], transformed, fixed = TRUE)
|
|
||||||
|
|
||||||
# parse it
|
if (!identical(c(locs), -1L)) {
|
||||||
rfile <- tempfile("renv-json-", fileext = ".R")
|
|
||||||
on.exit(unlink(rfile), add = TRUE)
|
|
||||||
writeLines(transformed, con = rfile)
|
|
||||||
json <- parse(rfile, keep.source = FALSE, srcfile = NULL)[[1L]]
|
|
||||||
|
|
||||||
# evaluate in safe environment
|
# get the string values
|
||||||
result <- eval(json, envir = renv_json_read_envir())
|
starts <- locs
|
||||||
|
ends <- locs + attr(locs, "match.length") - 1L
|
||||||
|
strings <- substring(text, starts, ends)
|
||||||
|
|
||||||
# fix up strings if necessary -- do so only with reversible patterns
|
# only keep those requiring escaping
|
||||||
patterns <- Filter(function(pattern) pattern[[3L]], patterns)
|
strings <- grep("[[\\]{}:]", strings, perl = TRUE, value = TRUE)
|
||||||
renv_json_read_remap(result, patterns)
|
|
||||||
|
# compute replacements
|
||||||
|
replacements <- sprintf('"\032%i\032"', seq_along(strings))
|
||||||
|
|
||||||
|
# replace the strings
|
||||||
|
mapply(function(string, replacement) {
|
||||||
|
replaced <<- sub(string, replacement, replaced, fixed = TRUE)
|
||||||
|
}, strings, replacements)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# transform the JSON into something the R parser understands
|
||||||
|
transformed <- replaced
|
||||||
|
transformed <- gsub("{}", "`names<-`(list(), character())", transformed, fixed = TRUE)
|
||||||
|
transformed <- gsub("[[{]", "list(", transformed, perl = TRUE)
|
||||||
|
transformed <- gsub("[]}]", ")", transformed, perl = TRUE)
|
||||||
|
transformed <- gsub(":", "=", transformed, fixed = TRUE)
|
||||||
|
text <- paste(transformed, collapse = "\n")
|
||||||
|
|
||||||
|
# parse it
|
||||||
|
json <- parse(text = text, keep.source = FALSE, srcfile = NULL)[[1L]]
|
||||||
|
|
||||||
|
# construct map between source strings, replaced strings
|
||||||
|
map <- as.character(parse(text = strings))
|
||||||
|
names(map) <- as.character(parse(text = replacements))
|
||||||
|
|
||||||
|
# convert to list
|
||||||
|
map <- as.list(map)
|
||||||
|
|
||||||
|
# remap strings in object
|
||||||
|
remapped <- renv_json_read_remap(json, map)
|
||||||
|
|
||||||
|
# evaluate
|
||||||
|
eval(remapped, envir = baseenv())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
renv_json_read_remap <- function(json, map) {
|
||||||
|
|
||||||
|
# fix names
|
||||||
|
if (!is.null(names(json))) {
|
||||||
|
lhs <- match(names(json), names(map), nomatch = 0L)
|
||||||
|
rhs <- match(names(map), names(json), nomatch = 0L)
|
||||||
|
names(json)[rhs] <- map[lhs]
|
||||||
|
}
|
||||||
|
|
||||||
|
# fix values
|
||||||
|
if (is.character(json))
|
||||||
|
return(map[[json]] %||% json)
|
||||||
|
|
||||||
|
# handle true, false, null
|
||||||
|
if (is.name(json)) {
|
||||||
|
text <- as.character(json)
|
||||||
|
if (text == "true")
|
||||||
|
return(TRUE)
|
||||||
|
else if (text == "false")
|
||||||
|
return(FALSE)
|
||||||
|
else if (text == "null")
|
||||||
|
return(NULL)
|
||||||
|
}
|
||||||
|
|
||||||
|
# recurse
|
||||||
|
if (is.recursive(json)) {
|
||||||
|
for (i in seq_along(json)) {
|
||||||
|
json[i] <- list(renv_json_read_remap(json[[i]], map))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
# load the renv profile, if any
|
# load the renv profile, if any
|
||||||
renv_bootstrap_profile_load(project)
|
renv_bootstrap_profile_load(project)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue