Compare commits

..

No commits in common. "2a39655e96bbbafbd60486797311720c7399ffcc" and "1613386096bb9657d1912f6ef03feca5b41f5d0c" have entirely different histories.

29 changed files with 208 additions and 323 deletions

View file

@ -9,7 +9,7 @@ type: software
license: AGPL-3.0-or-later license: AGPL-3.0-or-later
title: 'FreesearchR: A free and open-source browser based data analysis tool for researchers title: 'FreesearchR: A free and open-source browser based data analysis tool for researchers
with publication ready output' with publication ready output'
version: 25.5.4 version: 25.5.2
doi: 10.5281/zenodo.14527429 doi: 10.5281/zenodo.14527429
identifiers: identifiers:
- type: url - type: url

View file

@ -1,6 +1,6 @@
Package: FreesearchR Package: FreesearchR
Title: A free and open-source browser based data analysis tool for researchers with publication ready output Title: A free and open-source browser based data analysis tool for researchers with publication ready output
Version: 25.5.4 Version: 25.5.2
Authors@R: c( Authors@R: c(
person("Andreas Gammelgaard", "Damsbo",email="agdamsbo@clin.au.dk", role = c("aut", "cre"), person("Andreas Gammelgaard", "Damsbo",email="agdamsbo@clin.au.dk", role = c("aut", "cre"),
comment = c(ORCID = "0000-0002-7559-1154")), comment = c(ORCID = "0000-0002-7559-1154")),

View file

@ -108,7 +108,6 @@ export(sankey_ready)
export(selectInputIcon) export(selectInputIcon)
export(set_column_label) export(set_column_label)
export(show_data) export(show_data)
export(simple_snake)
export(sort_by) export(sort_by)
export(specify_qmd_format) export(specify_qmd_format)
export(subset_types) export(subset_types)
@ -131,6 +130,7 @@ export(write_quarto)
importFrom(classInt,classIntervals) importFrom(classInt,classIntervals)
importFrom(data.table,as.data.table) importFrom(data.table,as.data.table)
importFrom(data.table,data.table) importFrom(data.table,data.table)
importFrom(grDevices,col2rgb)
importFrom(graphics,abline) importFrom(graphics,abline)
importFrom(graphics,axis) importFrom(graphics,axis)
importFrom(graphics,hist) importFrom(graphics,hist)
@ -141,6 +141,7 @@ importFrom(htmltools,css)
importFrom(htmltools,tagList) importFrom(htmltools,tagList)
importFrom(htmltools,tags) importFrom(htmltools,tags)
importFrom(htmltools,validateCssUnit) importFrom(htmltools,validateCssUnit)
importFrom(phosphoricons,ph)
importFrom(rlang,"%||%") importFrom(rlang,"%||%")
importFrom(rlang,call2) importFrom(rlang,call2)
importFrom(rlang,expr) importFrom(rlang,expr)
@ -159,20 +160,25 @@ importFrom(shiny,isTruthy)
importFrom(shiny,modalDialog) importFrom(shiny,modalDialog)
importFrom(shiny,moduleServer) importFrom(shiny,moduleServer)
importFrom(shiny,numericInput) importFrom(shiny,numericInput)
importFrom(shiny,observe)
importFrom(shiny,observeEvent) importFrom(shiny,observeEvent)
importFrom(shiny,plotOutput) importFrom(shiny,plotOutput)
importFrom(shiny,reactive) importFrom(shiny,reactive)
importFrom(shiny,reactiveValues) importFrom(shiny,reactiveValues)
importFrom(shiny,renderPlot) importFrom(shiny,renderPlot)
importFrom(shiny,renderUI)
importFrom(shiny,req) importFrom(shiny,req)
importFrom(shiny,restoreInput) importFrom(shiny,restoreInput)
importFrom(shiny,selectizeInput) importFrom(shiny,selectizeInput)
importFrom(shiny,showModal) importFrom(shiny,showModal)
importFrom(shiny,tagList) importFrom(shiny,tagList)
importFrom(shiny,textAreaInput)
importFrom(shiny,textInput) importFrom(shiny,textInput)
importFrom(shiny,uiOutput) importFrom(shiny,uiOutput)
importFrom(shiny,updateActionButton) importFrom(shiny,updateActionButton)
importFrom(shiny,updateTextAreaInput)
importFrom(shinyWidgets,WinBox) importFrom(shinyWidgets,WinBox)
importFrom(shinyWidgets,alert)
importFrom(shinyWidgets,noUiSliderInput) importFrom(shinyWidgets,noUiSliderInput)
importFrom(shinyWidgets,prettyCheckbox) importFrom(shinyWidgets,prettyCheckbox)
importFrom(shinyWidgets,updateVirtualSelect) importFrom(shinyWidgets,updateVirtualSelect)

18
NEWS.md
View file

@ -1,21 +1,3 @@
# FreesearchR 25.5.4
- *FIX* correctly omit NAs in `data_type()` call
- *FIX* omit NAs when plotting Euler diagrams.
- *FIX* print correct labels in horizontal stacked bars.
- *FIX* initial app load should feel faster.
# FreesearchR 25.5.3
- *FIX* a little polish on the data import
- *FIX* polished REDCap import and new code to reference the `REDCapCAST::easy_redcap()` function.
- *FIX* updated documentation to reflect new private hosting on a Hetzner server in Germany.
# FreesearchR 25.5.2 # FreesearchR 25.5.2
- *FIX*: correct export of plots. The solution in the last version broke more than it solved. - *FIX*: correct export of plots. The solution in the last version broke more than it solved.

View file

@ -1 +1 @@
app_version <- function()'25.5.4' app_version <- function()'25.5.2'

View file

@ -25,6 +25,7 @@
#' contrast_text(c("#F2F2F2", "blue"), method="relative") #' contrast_text(c("#F2F2F2", "blue"), method="relative")
#' @export #' @export
#' #'
#' @importFrom grDevices col2rgb
#' #'
contrast_text <- function(background, contrast_text <- function(background,
light_text = 'white', light_text = 'white',

View file

@ -17,17 +17,20 @@
#' @export #' @export
#' #'
#' @importFrom htmltools tagList tags css #' @importFrom htmltools tagList tags css
#' @importFrom shiny NS textInput textAreaInput uiOutput actionButton
#' @importFrom phosphoricons ph
#' @importFrom shinyWidgets virtualSelectInput
#' #'
#' @name create-column #' @name create-column
#' #'
#' @example examples/create_column_module_demo.R #' @example examples/create_column_module_demo.R
create_column_ui <- function(id) { create_column_ui <- function(id) {
ns <- NS(id) ns <- NS(id)
htmltools::tagList( tagList(
# datamods:::html_dependency_datamods(), # datamods:::html_dependency_datamods(),
# html_dependency_FreesearchR(), # html_dependency_FreesearchR(),
shiny::tags$head( tags$head(
shiny::tags$link(rel = "stylesheet", type = "text/css", href = "FreesearchR/inst/assets/css/FreesearchR.css") tags$link(rel = "stylesheet", type = "text/css", href = "FreesearchR/inst/assets/css/FreesearchR.css")
), ),
# tags$head( # tags$head(
# # Note the wrapping of the string in HTML() # # Note the wrapping of the string in HTML()
@ -81,7 +84,7 @@ create_column_ui <- function(id) {
) )
) )
), ),
shiny::textAreaInput( textAreaInput(
inputId = ns("expression"), inputId = ns("expression"),
label = i18n("Enter an expression to define new column:"), label = i18n("Enter an expression to define new column:"),
value = "", value = "",
@ -129,6 +132,9 @@ create_column_ui <- function(id) {
#' #'
#' @rdname create-column #' @rdname create-column
#' #'
#' @importFrom shiny moduleServer reactiveValues observeEvent renderUI req
#' updateTextAreaInput reactive bindEvent observe
#' @importFrom shinyWidgets alert updateVirtualSelect
create_column_server <- function(id, create_column_server <- function(id,
data_r = reactive(NULL), data_r = reactive(NULL),
allowed_operations = list_allowed_operations()) { allowed_operations = list_allowed_operations()) {

View file

@ -1,3 +1,9 @@
library(datamods)
library(toastui)
library(phosphoricons)
library(rlang)
library(shiny)
#' Extended cutting function with fall-back to the native base::cut #' Extended cutting function with fall-back to the native base::cut
#' #'
#' @param x an object inheriting from class "hms" #' @param x an object inheriting from class "hms"
@ -206,9 +212,9 @@ cut_variable_ui <- function(id) {
shiny::fluidRow( shiny::fluidRow(
column( column(
width = 3, width = 3,
shinyWidgets::virtualSelectInput( virtualSelectInput(
inputId = ns("variable"), inputId = ns("variable"),
label = datamods:::i18n("Variable to cut:"), label = i18n("Variable to cut:"),
choices = NULL, choices = NULL,
width = "100%" width = "100%"
) )
@ -221,7 +227,7 @@ cut_variable_ui <- function(id) {
width = 3, width = 3,
numericInput( numericInput(
inputId = ns("n_breaks"), inputId = ns("n_breaks"),
label = datamods:::i18n("Number of breaks:"), label = i18n("Number of breaks:"),
value = 3, value = 3,
min = 2, min = 2,
max = 12, max = 12,
@ -232,12 +238,12 @@ cut_variable_ui <- function(id) {
width = 3, width = 3,
checkboxInput( checkboxInput(
inputId = ns("right"), inputId = ns("right"),
label = datamods:::i18n("Close intervals on the right"), label = i18n("Close intervals on the right"),
value = TRUE value = TRUE
), ),
checkboxInput( checkboxInput(
inputId = ns("include_lowest"), inputId = ns("include_lowest"),
label = datamods:::i18n("Include lowest value"), label = i18n("Include lowest value"),
value = TRUE value = TRUE
) )
) )
@ -248,10 +254,10 @@ cut_variable_ui <- function(id) {
uiOutput(outputId = ns("slider_fixed")) uiOutput(outputId = ns("slider_fixed"))
), ),
plotOutput(outputId = ns("plot"), width = "100%", height = "270px"), plotOutput(outputId = ns("plot"), width = "100%", height = "270px"),
toastui::datagridOutput2(outputId = ns("count")), datagridOutput2(outputId = ns("count")),
actionButton( actionButton(
inputId = ns("create"), inputId = ns("create"),
label = tagList(phosphoricons::ph("scissors"), datamods:::i18n("Create factor variable")), label = tagList(ph("scissors"), i18n("Create factor variable")),
class = "btn-outline-primary float-end" class = "btn-outline-primary float-end"
), ),
tags$div(class = "clearfix") tags$div(class = "clearfix")
@ -282,7 +288,7 @@ cut_variable_server <- function(id, data_r = reactive(NULL)) {
is.numeric(.x) || is_datetime(.x) is.numeric(.x) || is_datetime(.x)
}, logical(1)) }, logical(1))
vars_num <- names(vars_num)[vars_num] vars_num <- names(vars_num)[vars_num]
shinyWidgets::updateVirtualSelect( updateVirtualSelect(
inputId = "variable", inputId = "variable",
choices = vars_num, choices = vars_num,
selected = if (isTruthy(input$variable)) input$variable else vars_num[1] selected = if (isTruthy(input$variable)) input$variable else vars_num[1]
@ -319,9 +325,9 @@ cut_variable_server <- function(id, data_r = reactive(NULL)) {
} }
shinyWidgets::noUiSliderInput( noUiSliderInput(
inputId = session$ns("fixed_brks"), inputId = session$ns("fixed_brks"),
label = datamods:::i18n("Fixed breaks:"), label = i18n("Fixed breaks:"),
min = lower, min = lower,
max = upper, max = upper,
value = brks, value = brks,
@ -376,7 +382,7 @@ cut_variable_server <- function(id, data_r = reactive(NULL)) {
shinyWidgets::virtualSelectInput( shinyWidgets::virtualSelectInput(
inputId = session$ns("method"), inputId = session$ns("method"),
label = datamods:::i18n("Method:"), label = i18n("Method:"),
choices = choices, choices = choices,
selected = NULL, selected = NULL,
width = "100%" width = "100%"
@ -519,7 +525,7 @@ cut_variable_server <- function(id, data_r = reactive(NULL)) {
data data
}) })
output$count <- toastui::renderDatagrid2({ output$count <- renderDatagrid2({
# shiny::req(rv$new_var_name) # shiny::req(rv$new_var_name)
data <- req(data_cutted_r()) data <- req(data_cutted_r())
# variable <- req(input$variable) # variable <- req(input$variable)
@ -535,14 +541,14 @@ cut_variable_server <- function(id, data_r = reactive(NULL)) {
datamods:::apply_grid_theme() datamods:::apply_grid_theme()
} }
on.exit(toastui::reset_grid_theme()) on.exit(toastui::reset_grid_theme())
grid <- toastui::datagrid( grid <- datagrid(
data = count_data, data = count_data,
colwidths = "guess", colwidths = "guess",
theme = "default", theme = "default",
bodyHeight = "auto" bodyHeight = "auto"
) )
grid <- toastui::grid_columns(grid, className = "font-monospace") grid <- toastui::grid_columns(grid, className = "font-monospace")
toastui::grid_colorbar( grid_colorbar(
grid, grid,
column = "count", column = "count",
label_outside = TRUE, label_outside = TRUE,
@ -570,7 +576,7 @@ cut_variable_server <- function(id, data_r = reactive(NULL)) {
#' #'
#' @rdname cut-variable #' @rdname cut-variable
modal_cut_variable <- function(id, modal_cut_variable <- function(id,
title = datamods:::i18n("Convert Numeric to Factor"), title = i18n("Convert Numeric to Factor"),
easyClose = TRUE, easyClose = TRUE,
size = "l", size = "l",
footer = NULL) { footer = NULL) {

View file

@ -681,7 +681,6 @@ create_plot <- function(data, type, pri, sec, ter = NULL, ...) {
#' mtcars |> get_label() #' mtcars |> get_label()
#' mtcars$mpg |> get_label() #' mtcars$mpg |> get_label()
#' gtsummary::trial |> get_label(var = "trt") #' gtsummary::trial |> get_label(var = "trt")
#' gtsummary::trial$trt |> get_label()
#' 1:10 |> get_label() #' 1:10 |> get_label()
get_label <- function(data, var = NULL) { get_label <- function(data, var = NULL) {
# data <- if (is.reactive(data)) data() else data # data <- if (is.reactive(data)) data() else data

View file

@ -35,7 +35,7 @@ show_data <- function(data,
if (is.null(options)) if (is.null(options))
options <- list() options <- list()
options$height <- 500 options$height <- 550
options$minBodyHeight <- 400 options$minBodyHeight <- 400
options$data <- data options$data <- data
options$theme <- "default" options$theme <- "default"

View file

@ -652,17 +652,3 @@ is_identical_to_previous <- function(data, no.name = TRUE) {
} }
}, FUN.VALUE = logical(1)) }, FUN.VALUE = logical(1))
} }
#' Simplified version of the snakecase packages to_snake_case
#'
#' @param data character string vector
#'
#' @returns vector
#' @export
#'
#' @examples
#' c("foo bar", "fooBar21", "!!Foo'B'a-r", "foo_bar", "F OO bar") |> simple_snake()
simple_snake <- function(data){
gsub("[\\s+]","_",gsub("[^\\w\\s:-]", "", tolower(data), perl=TRUE), perl=TRUE)
}

View file

@ -1 +1 @@
hosted_version <- function()'v25.5.4-250510' hosted_version <- function()'v25.5.2-250508'

View file

@ -87,11 +87,10 @@ plot_euler <- function(data, pri, sec, ter = NULL, seed = 2103) {
out <- lapply(ds, \(.x){ out <- lapply(ds, \(.x){
.x[c(pri, sec)] |> .x[c(pri, sec)] |>
as.data.frame() |> as.data.frame() |>
na.omit() |>
plot_euler_single() plot_euler_single()
}) })
# names(out) # names(out)
wrap_plot_list(out) wrap_plot_list(out)
# patchwork::wrap_plots(out, guides = "collect") # patchwork::wrap_plots(out, guides = "collect")
} }

View file

@ -62,8 +62,9 @@ vertical_stacked_bars <- function(data,
contrast_cut <- contrast_cut <-
sum(contrast_text(colors, threshold = .3) == "white") sum(contrast_text(colors, threshold = .3) == "white")
score_label <- data |> get_label(var = score) score_label <- ifelse(is.na(REDCapCAST::get_attr(data$score, "label")), score, REDCapCAST::get_attr(data$score, "label"))
group_label <- data |> get_label(var = group) group_label <- ifelse(is.na(REDCapCAST::get_attr(data$group, "label")), group, REDCapCAST::get_attr(data$group, "label"))
p |> p |>
(\(.x){ (\(.x){

View file

@ -119,6 +119,7 @@ plot_sankey <- function(data, pri, sec, ter = NULL, color.group = "pri", colors
#' plot_sankey_single("first", "last", color.group = "pri") #' plot_sankey_single("first", "last", color.group = "pri")
#' mtcars |> #' mtcars |>
#' default_parsing() |> #' default_parsing() |>
#' str()
#' plot_sankey_single("cyl", "vs", color.group = "pri") #' plot_sankey_single("cyl", "vs", color.group = "pri")
plot_sankey_single <- function(data, pri, sec, color.group = c("pri", "sec"), colors = NULL, ...) { plot_sankey_single <- function(data, pri, sec, color.group = c("pri", "sec"), colors = NULL, ...) {
color.group <- match.arg(color.group) color.group <- match.arg(color.group)
@ -131,6 +132,8 @@ plot_sankey_single <- function(data, pri, sec, color.group = c("pri", "sec"), co
data <- data |> sankey_ready(pri = pri, sec = sec, ...) data <- data |> sankey_ready(pri = pri, sec = sec, ...)
library(ggalluvial)
na.color <- "#2986cc" na.color <- "#2986cc"
box.color <- "#1E4B66" box.color <- "#1E4B66"
@ -194,8 +197,6 @@ plot_sankey_single <- function(data, pri, sec, color.group = c("pri", "sec"), co
) )
} }
## Will fail to use stat="stratum" if library is not loaded.
library(ggalluvial)
p + p +
ggplot2::geom_text( ggplot2::geom_text(
stat = "stratum", stat = "stratum",

0
R/redcap.R Normal file
View file

View file

@ -200,12 +200,9 @@ m_redcap_readServer <- function(id) {
) )
# browser() # browser()
shiny::withProgress( shiny::withProgress({
{ imported <- try(rlang::exec(REDCapR::redcap_metadata_read, !!!parameters), silent = TRUE)
imported <- try(rlang::exec(REDCapR::redcap_metadata_read, !!!parameters), silent = TRUE) },message = paste("Connecting to",data_rv$uri))
},
message = paste("Connecting to", data_rv$uri)
)
## TODO: Simplify error messages ## TODO: Simplify error messages
if (inherits(imported, "try-error") || NROW(imported) < 1 || ifelse(is.list(imported), !isTRUE(imported$success), FALSE)) { if (inherits(imported, "try-error") || NROW(imported) < 1 || ifelse(is.list(imported), !isTRUE(imported$success), FALSE)) {
@ -231,7 +228,7 @@ m_redcap_readServer <- function(id) {
status = "success", status = "success",
include_data_alert( include_data_alert(
see_data_text = "Click to see data dictionary", see_data_text = "Click to see data dictionary",
dataIdName = "see_dd", dataIdName = "see_data",
extra = tags$p( extra = tags$p(
tags$b(phosphoricons::ph("check", weight = "bold"), "Connected to server!"), tags$b(phosphoricons::ph("check", weight = "bold"), "Connected to server!"),
glue::glue("The {data_rv$info$project_title} project is loaded.") glue::glue("The {data_rv$info$project_title} project is loaded.")
@ -257,8 +254,8 @@ m_redcap_readServer <- function(id) {
output$connect_success <- shiny::reactive(identical(data_rv$dd_status, "success")) output$connect_success <- shiny::reactive(identical(data_rv$dd_status, "success"))
shiny::outputOptions(output, "connect_success", suspendWhenHidden = FALSE) shiny::outputOptions(output, "connect_success", suspendWhenHidden = FALSE)
shiny::observeEvent(input$see_dd, { shiny::observeEvent(input$see_data, {
show_data( datamods::show_data(
purrr::pluck(data_rv$dd_list, "data"), purrr::pluck(data_rv$dd_list, "data"),
title = "Data dictionary", title = "Data dictionary",
type = "modal", type = "modal",
@ -267,17 +264,6 @@ m_redcap_readServer <- function(id) {
) )
}) })
shiny::observeEvent(input$see_data, {
show_data(
# purrr::pluck(data_rv$dd_list, "data"),
data_rv$data,
title = "Imported data set",
type = "modal",
show_classes = FALSE,
tags$b("Preview:")
)
})
arms <- shiny::reactive({ arms <- shiny::reactive({
shiny::req(input$api) shiny::req(input$api)
shiny::req(data_rv$uri) shiny::req(data_rv$uri)
@ -392,24 +378,13 @@ m_redcap_readServer <- function(id) {
imported <- try(rlang::exec(REDCapCAST::read_redcap_tables, !!!parameters), silent = TRUE) imported <- try(rlang::exec(REDCapCAST::read_redcap_tables, !!!parameters), silent = TRUE)
}) })
parameters_code <- parameters[c("uri", "fields", "events", "raw_or_label", "filter_logic")] code <- rlang::call2("read_redcap_tables",
!!!utils::modifyList(parameters, list(token = "PERSONAL_API_TOKEN")), ,
code <- rlang::call2(
"easy_redcap",
!!!utils::modifyList(
parameters_code,
list(
data_format = ifelse(
input$data_type == "long" && !is.null(input$data_type),
"long",
"wide"
),
project.name = simple_snake(data_rv$info$project_title)
)
),
.ns = "REDCapCAST" .ns = "REDCapCAST"
) )
# browser()
if (inherits(imported, "try-error") || NROW(imported) < 1) { if (inherits(imported, "try-error") || NROW(imported) < 1) {
data_rv$data_status <- "error" data_rv$data_status <- "error"
data_rv$data_list <- NULL data_rv$data_list <- NULL
@ -478,17 +453,9 @@ m_redcap_readServer <- function(id) {
datamods:::insert_alert( datamods:::insert_alert(
selector = ns("retrieved"), selector = ns("retrieved"),
status = data_rv$data_status, status = data_rv$data_status,
# tags$p( tags$p(
# tags$b(phosphoricons::ph("check", weight = "bold"), "Success!"), tags$b(phosphoricons::ph("check", weight = "bold"), "Success!"),
# data_rv$data_message data_rv$data_message
# ),
include_data_alert(
see_data_text = "Click to see the imported data",
dataIdName = "see_data",
extra = tags$p(
tags$b(phosphoricons::ph("check", weight = "bold"), data_rv$data_message)
),
btn_show_data = TRUE
) )
) )
} else { } else {

View file

@ -271,13 +271,12 @@ data_type <- function(data) {
sapply(data, data_type) sapply(data, data_type)
} else { } else {
cl_d <- class(data) cl_d <- class(data)
l_unique <- length(unique(na.omit(data)))
if (all(is.na(data))) { if (all(is.na(data))) {
out <- "empty" out <- "empty"
} else if (l_unique < 2) { } else if (length(unique(data)) < 2) {
out <- "monotone" out <- "monotone"
} else if (any(c("factor", "logical") %in% cl_d) | l_unique == 2) { } else if (any(c("factor", "logical") %in% cl_d) | length(unique(data)) == 2) {
if (identical("logical", cl_d) | l_unique == 2) { if (identical("logical", cl_d) | length(unique(data)) == 2) {
out <- "dichotomous" out <- "dichotomous"
} else { } else {
# if (is.ordered(data)) { # if (is.ordered(data)) {
@ -290,7 +289,7 @@ data_type <- function(data) {
out <- "text" out <- "text"
} else if (any(c("hms", "Date", "POSIXct", "POSIXt") %in% cl_d)) { } else if (any(c("hms", "Date", "POSIXct", "POSIXt") %in% cl_d)) {
out <- "datetime" out <- "datetime"
} else if (l_unique > 2) { } else if (!length(unique(data)) == 2) {
## Previously had all thinkable classes ## Previously had all thinkable classes
## Now just assumes the class has not been defined above ## Now just assumes the class has not been defined above
## any(c("numeric", "integer", "hms", "Date", "timediff") %in% cl_d) & ## any(c("numeric", "integer", "hms", "Date", "timediff") %in% cl_d) &

Binary file not shown.

View file

@ -31,7 +31,7 @@ update_factor_ui <- function(id) {
fluidRow( fluidRow(
column( column(
width = 6, width = 6,
shinyWidgets::virtualSelectInput( virtualSelectInput(
inputId = ns("variable"), inputId = ns("variable"),
label = i18n("Factor variable to reorder:"), label = i18n("Factor variable to reorder:"),
choices = NULL, choices = NULL,
@ -66,10 +66,10 @@ update_factor_ui <- function(id) {
) )
) )
), ),
toastui::datagridOutput(ns("grid")), datagridOutput(ns("grid")),
tags$div( tags$div(
class = "float-end", class = "float-end",
shinyWidgets::prettyCheckbox( prettyCheckbox(
inputId = ns("new_var"), inputId = ns("new_var"),
label = i18n("Create a new variable (otherwise replaces the one selected)"), label = i18n("Create a new variable (otherwise replaces the one selected)"),
value = FALSE, value = FALSE,

View file

@ -1,3 +1,7 @@
library(data.table)
library(rlang)
#' Select, rename and convert variables #' Select, rename and convert variables
#' #'
#' @param id Module id. See [shiny::moduleServer()]. #' @param id Module id. See [shiny::moduleServer()].

View file

@ -7,9 +7,9 @@
[![FreesearchR](https://img.shields.io/badge/Shiny-shinyapps.io-blue?style=flat&labelColor=white&logo=RStudio&logoColor=blue)](https://agdamsbo.shinyapps.io/FreesearchR/) [![FreesearchR](https://img.shields.io/badge/Shiny-shinyapps.io-blue?style=flat&labelColor=white&logo=RStudio&logoColor=blue)](https://agdamsbo.shinyapps.io/FreesearchR/)
<!-- badges: end --> <!-- badges: end -->
The [***FreesearchR***](https://app.freesearchr.org) is a simple, clinical health data exploration and analysis tool to democratise clinical research by assisting any researcher to easily evaluate and analyse data and export publication ready results. The [***FreesearchR***](https://agdamsbo.shinyapps.io/FreesearchR/) is a simple, clinical health data exploration and analysis tool to democratise clinical research by assisting any researcher to easily evaluate and analyse data and export publication ready results.
[***FreesearchR***](https://app.freesearchr.org) is free and open-source, and is [accessible in your web browser through this link](https://app.freesearchr.org). The app can also run locally, please [see below](#run-locally-on-your-own-machine-sec-run-locally). [***FreesearchR***](https://agdamsbo.shinyapps.io/FreesearchR/) is free and open-source, and is directly accessible here: [link to the app freely hosted on shinyapps.io](https://agdamsbo.shinyapps.io/FreesearchR/). The app can also run locally, please see below.
All feedback is welcome and can be shared as a GitHub issue. Any suggestions on collaboration is much welcomed. Please reach out! All feedback is welcome and can be shared as a GitHub issue. Any suggestions on collaboration is much welcomed. Please reach out!

View file

@ -11,11 +11,11 @@
|collate |en_US.UTF-8 | |collate |en_US.UTF-8 |
|ctype |en_US.UTF-8 | |ctype |en_US.UTF-8 |
|tz |Europe/Copenhagen | |tz |Europe/Copenhagen |
|date |2025-05-10 | |date |2025-05-08 |
|rstudio |2024.12.1+563 Kousa Dogwood (desktop) | |rstudio |2024.12.1+563 Kousa Dogwood (desktop) |
|pandoc |3.6.4 @ /opt/homebrew/bin/ (via rmarkdown) | |pandoc |3.6.4 @ /opt/homebrew/bin/ (via rmarkdown) |
|quarto |1.7.30 @ /usr/local/bin/quarto | |quarto |1.6.40 @ /usr/local/bin/quarto |
|FreesearchR |25.5.4.250510 | |FreesearchR |25.5.2.250508 |
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -44,6 +44,7 @@
|commonmark |1.9.5 |2025-03-17 |CRAN (R 4.4.1) | |commonmark |1.9.5 |2025-03-17 |CRAN (R 4.4.1) |
|correlation |0.8.7 |2025-03-03 |CRAN (R 4.4.1) | |correlation |0.8.7 |2025-03-03 |CRAN (R 4.4.1) |
|crayon |1.5.3 |2024-06-20 |CRAN (R 4.4.1) | |crayon |1.5.3 |2024-06-20 |CRAN (R 4.4.1) |
|crosstalk |1.2.1 |2023-11-23 |CRAN (R 4.4.0) |
|curl |6.2.2 |2025-03-24 |CRAN (R 4.4.1) | |curl |6.2.2 |2025-03-24 |CRAN (R 4.4.1) |
|data.table |1.17.0 |2025-02-22 |CRAN (R 4.4.1) | |data.table |1.17.0 |2025-02-22 |CRAN (R 4.4.1) |
|datamods |1.5.3 |2024-10-02 |CRAN (R 4.4.1) | |datamods |1.5.3 |2024-10-02 |CRAN (R 4.4.1) |
@ -58,7 +59,6 @@
|easystats |0.7.4 |2025-02-06 |CRAN (R 4.4.1) | |easystats |0.7.4 |2025-02-06 |CRAN (R 4.4.1) |
|effectsize |1.0.0 |2024-12-10 |CRAN (R 4.4.1) | |effectsize |1.0.0 |2024-12-10 |CRAN (R 4.4.1) |
|ellipsis |0.3.2 |2021-04-29 |CRAN (R 4.4.1) | |ellipsis |0.3.2 |2021-04-29 |CRAN (R 4.4.1) |
|eulerr |7.0.2 |2024-03-28 |CRAN (R 4.4.0) |
|evaluate |1.0.3 |2025-01-10 |CRAN (R 4.4.1) | |evaluate |1.0.3 |2025-01-10 |CRAN (R 4.4.1) |
|farver |2.1.2 |2024-05-13 |CRAN (R 4.4.1) | |farver |2.1.2 |2024-05-13 |CRAN (R 4.4.1) |
|fastmap |1.2.0 |2024-05-15 |CRAN (R 4.4.1) | |fastmap |1.2.0 |2024-05-15 |CRAN (R 4.4.1) |
@ -66,11 +66,8 @@
|forcats |1.0.0 |2023-01-29 |CRAN (R 4.4.0) | |forcats |1.0.0 |2023-01-29 |CRAN (R 4.4.0) |
|fs |1.6.6 |2025-04-12 |CRAN (R 4.4.1) | |fs |1.6.6 |2025-04-12 |CRAN (R 4.4.1) |
|generics |0.1.3 |2022-07-05 |CRAN (R 4.4.1) | |generics |0.1.3 |2022-07-05 |CRAN (R 4.4.1) |
|ggalluvial |0.12.5 |2023-02-22 |CRAN (R 4.4.0) |
|ggforce |0.4.2 |2024-02-19 |CRAN (R 4.4.0) |
|ggplot2 |3.5.2 |2025-04-09 |CRAN (R 4.4.1) | |ggplot2 |3.5.2 |2025-04-09 |CRAN (R 4.4.1) |
|glue |1.8.0 |2024-09-30 |CRAN (R 4.4.1) | |glue |1.8.0 |2024-09-30 |CRAN (R 4.4.1) |
|gridExtra |2.3 |2017-09-09 |CRAN (R 4.4.1) |
|gt |1.0.0 |2025-04-05 |CRAN (R 4.4.1) | |gt |1.0.0 |2025-04-05 |CRAN (R 4.4.1) |
|gtable |0.3.6 |2024-10-25 |CRAN (R 4.4.1) | |gtable |0.3.6 |2024-10-25 |CRAN (R 4.4.1) |
|gtsummary |2.2.0 |2025-04-14 |CRAN (R 4.4.1) | |gtsummary |2.2.0 |2025-04-14 |CRAN (R 4.4.1) |
@ -88,7 +85,6 @@
|KernSmooth |2.23-26 |2025-01-01 |CRAN (R 4.4.1) | |KernSmooth |2.23-26 |2025-01-01 |CRAN (R 4.4.1) |
|keyring |1.3.2 |2023-12-11 |CRAN (R 4.4.0) | |keyring |1.3.2 |2023-12-11 |CRAN (R 4.4.0) |
|knitr |1.50 |2025-03-16 |CRAN (R 4.4.1) | |knitr |1.50 |2025-03-16 |CRAN (R 4.4.1) |
|labeling |0.4.3 |2023-08-29 |CRAN (R 4.4.1) |
|later |1.4.2 |2025-04-08 |CRAN (R 4.4.1) | |later |1.4.2 |2025-04-08 |CRAN (R 4.4.1) |
|lattice |0.22-7 |2025-04-02 |CRAN (R 4.4.1) | |lattice |0.22-7 |2025-04-02 |CRAN (R 4.4.1) |
|lifecycle |1.0.4 |2023-11-07 |CRAN (R 4.4.1) | |lifecycle |1.0.4 |2023-11-07 |CRAN (R 4.4.1) |
@ -105,6 +101,7 @@
|nloptr |2.2.1 |2025-03-17 |CRAN (R 4.4.1) | |nloptr |2.2.1 |2025-03-17 |CRAN (R 4.4.1) |
|openssl |2.3.2 |2025-02-03 |CRAN (R 4.4.1) | |openssl |2.3.2 |2025-02-03 |CRAN (R 4.4.1) |
|openxlsx2 |1.15 |2025-04-25 |CRAN (R 4.4.1) | |openxlsx2 |1.15 |2025-04-25 |CRAN (R 4.4.1) |
|pak |0.8.0.2 |2025-04-08 |CRAN (R 4.4.1) |
|parameters |0.24.2 |2025-03-04 |CRAN (R 4.4.1) | |parameters |0.24.2 |2025-03-04 |CRAN (R 4.4.1) |
|patchwork |1.3.0 |2024-09-16 |CRAN (R 4.4.1) | |patchwork |1.3.0 |2024-09-16 |CRAN (R 4.4.1) |
|performance |0.13.0 |2025-01-15 |CRAN (R 4.4.1) | |performance |0.13.0 |2025-01-15 |CRAN (R 4.4.1) |
@ -113,8 +110,6 @@
|pkgbuild |1.4.7 |2025-03-24 |CRAN (R 4.4.1) | |pkgbuild |1.4.7 |2025-03-24 |CRAN (R 4.4.1) |
|pkgconfig |2.0.3 |2019-09-22 |CRAN (R 4.4.1) | |pkgconfig |2.0.3 |2019-09-22 |CRAN (R 4.4.1) |
|pkgload |1.4.0 |2024-06-28 |CRAN (R 4.4.0) | |pkgload |1.4.0 |2024-06-28 |CRAN (R 4.4.0) |
|polyclip |1.10-7 |2024-07-23 |CRAN (R 4.4.1) |
|polylabelr |0.3.0 |2024-11-19 |CRAN (R 4.4.1) |
|processx |3.8.6 |2025-02-21 |CRAN (R 4.4.1) | |processx |3.8.6 |2025-02-21 |CRAN (R 4.4.1) |
|profvis |0.4.0 |2024-09-20 |CRAN (R 4.4.1) | |profvis |0.4.0 |2024-09-20 |CRAN (R 4.4.1) |
|promises |1.3.2 |2024-11-28 |CRAN (R 4.4.1) | |promises |1.3.2 |2024-11-28 |CRAN (R 4.4.1) |
@ -127,8 +122,6 @@
|R.oo |1.27.0 |2024-11-01 |CRAN (R 4.4.1) | |R.oo |1.27.0 |2024-11-01 |CRAN (R 4.4.1) |
|R.utils |2.13.0 |2025-02-24 |CRAN (R 4.4.1) | |R.utils |2.13.0 |2025-02-24 |CRAN (R 4.4.1) |
|R6 |2.6.1 |2025-02-15 |CRAN (R 4.4.1) | |R6 |2.6.1 |2025-02-15 |CRAN (R 4.4.1) |
|ragg |1.4.0 |2025-04-10 |CRAN (R 4.4.1) |
|rankinPlot |1.1.0 |2023-01-30 |CRAN (R 4.4.0) |
|rbibutils |2.3 |2024-10-04 |CRAN (R 4.4.1) | |rbibutils |2.3 |2024-10-04 |CRAN (R 4.4.1) |
|RColorBrewer |1.1-3 |2022-04-03 |CRAN (R 4.4.1) | |RColorBrewer |1.1-3 |2022-04-03 |CRAN (R 4.4.1) |
|Rcpp |1.0.14 |2025-01-12 |CRAN (R 4.4.1) | |Rcpp |1.0.14 |2025-01-12 |CRAN (R 4.4.1) |
@ -146,7 +139,6 @@
|rio |1.2.3 |2024-09-25 |CRAN (R 4.4.1) | |rio |1.2.3 |2024-09-25 |CRAN (R 4.4.1) |
|rlang |1.1.6 |2025-04-11 |CRAN (R 4.4.1) | |rlang |1.1.6 |2025-04-11 |CRAN (R 4.4.1) |
|rmarkdown |2.29 |2024-11-04 |CRAN (R 4.4.1) | |rmarkdown |2.29 |2024-11-04 |CRAN (R 4.4.1) |
|roxygen2 |7.3.2 |2024-06-28 |CRAN (R 4.4.0) |
|rprojroot |2.0.4 |2023-11-05 |CRAN (R 4.4.1) | |rprojroot |2.0.4 |2023-11-05 |CRAN (R 4.4.1) |
|rsconnect |1.3.4 |2025-01-22 |CRAN (R 4.4.1) | |rsconnect |1.3.4 |2025-01-22 |CRAN (R 4.4.1) |
|rstudioapi |0.17.1 |2024-10-22 |CRAN (R 4.4.1) | |rstudioapi |0.17.1 |2024-10-22 |CRAN (R 4.4.1) |
@ -160,23 +152,16 @@
|shinyTime |1.0.3 |2022-08-19 |CRAN (R 4.4.0) | |shinyTime |1.0.3 |2022-08-19 |CRAN (R 4.4.0) |
|shinyWidgets |0.9.0 |2025-02-21 |CRAN (R 4.4.1) | |shinyWidgets |0.9.0 |2025-02-21 |CRAN (R 4.4.1) |
|stringi |1.8.7 |2025-03-27 |CRAN (R 4.4.1) | |stringi |1.8.7 |2025-03-27 |CRAN (R 4.4.1) |
|stringr |1.5.1 |2023-11-14 |CRAN (R 4.4.0) |
|styler |1.10.3 |2024-04-07 |CRAN (R 4.4.0) | |styler |1.10.3 |2024-04-07 |CRAN (R 4.4.0) |
|systemfonts |1.2.2 |2025-04-04 |CRAN (R 4.4.1) |
|textshaping |1.0.0 |2025-01-20 |CRAN (R 4.4.1) |
|tibble |3.2.1 |2023-03-20 |CRAN (R 4.4.0) | |tibble |3.2.1 |2023-03-20 |CRAN (R 4.4.0) |
|tidyr |1.3.1 |2024-01-24 |CRAN (R 4.4.1) | |tidyr |1.3.1 |2024-01-24 |CRAN (R 4.4.1) |
|tidyselect |1.2.1 |2024-03-11 |CRAN (R 4.4.0) | |tidyselect |1.2.1 |2024-03-11 |CRAN (R 4.4.0) |
|toastui |0.4.0 |2025-04-03 |CRAN (R 4.4.1) | |toastui |0.4.0 |2025-04-03 |CRAN (R 4.4.1) |
|tweenr |2.0.3 |2024-02-26 |CRAN (R 4.4.0) |
|tzdb |0.5.0 |2025-03-15 |CRAN (R 4.4.1) | |tzdb |0.5.0 |2025-03-15 |CRAN (R 4.4.1) |
|urlchecker |1.0.1 |2021-11-30 |CRAN (R 4.4.1) | |urlchecker |1.0.1 |2021-11-30 |CRAN (R 4.4.1) |
|usethis |3.1.0 |2024-11-26 |CRAN (R 4.4.1) | |usethis |3.1.0 |2024-11-26 |CRAN (R 4.4.1) |
|utf8 |1.2.4 |2023-10-22 |CRAN (R 4.4.1) |
|V8 |6.0.3 |2025-03-26 |CRAN (R 4.4.1) | |V8 |6.0.3 |2025-03-26 |CRAN (R 4.4.1) |
|vctrs |0.6.5 |2023-12-01 |CRAN (R 4.4.0) | |vctrs |0.6.5 |2023-12-01 |CRAN (R 4.4.0) |
|viridis |0.6.5 |2024-01-29 |CRAN (R 4.4.0) |
|viridisLite |0.4.2 |2023-05-02 |CRAN (R 4.4.1) |
|vroom |1.6.5 |2023-12-05 |CRAN (R 4.4.0) | |vroom |1.6.5 |2023-12-05 |CRAN (R 4.4.0) |
|withr |3.0.2 |2024-10-28 |CRAN (R 4.4.1) | |withr |3.0.2 |2024-10-28 |CRAN (R 4.4.1) |
|writexl |1.5.4 |2025-04-15 |CRAN (R 4.4.1) | |writexl |1.5.4 |2025-04-15 |CRAN (R 4.4.1) |

View file

@ -11,7 +11,7 @@ template:
# Adding the switch destroys the theme colors # Adding the switch destroys the theme colors
light-switch: false light-switch: false
includes: includes:
in_header: <script defer src="https://stats.freesearchr.org/script.js" data-website-id="85bfd1e8-2cbe-4a4a-aa34-1dfb2960905b"></script> in_header: <script defer src="https://analytics.gdamsbo.dk/script.js" data-website-id="1f3baf18-29aa-4612-931b-58ea35922ae4"></script>
navbar: navbar:
bg: primary bg: primary

View file

@ -1,44 +1,5 @@
########
#### Current file: /Users/au301842/FreesearchR/app/libs.R
########
library(shiny)
# library(shinyjs)
# library(methods)
# library(readr)
# library(MASS)
# library(stats)
# library(gt)
# library(openxlsx2)
# library(haven)
# library(readODS)
# library(bslib)
# library(assertthat)
# library(dplyr)
# library(quarto)
# library(here)
# library(broom)
# library(broom.helpers)
# library(easystats)
# library(patchwork)
# library(DHARMa)
# library(apexcharter)
library(toastui)
# library(datamods)
# library(IDEAFilter)
library(shinyWidgets)
# library(DT)
# library(data.table)
# library(gtsummary)
library(bsicons)
library(rlang)
# library(datamods)
# library(toastui)
# library(phosphoricons)
######## ########
#### Current file: /Users/au301842/FreesearchR/app/functions.R #### Current file: /Users/au301842/FreesearchR/app/functions.R
######## ########
@ -49,7 +10,7 @@ library(rlang)
#### Current file: /Users/au301842/FreesearchR/R//app_version.R #### Current file: /Users/au301842/FreesearchR/R//app_version.R
######## ########
app_version <- function()'25.5.3' app_version <- function()'25.5.2'
######## ########
@ -168,6 +129,7 @@ create_baseline <- function(data, ..., by.var, add.p = FALSE, add.overall = FALS
#' contrast_text(c("#F2F2F2", "blue"), method="relative") #' contrast_text(c("#F2F2F2", "blue"), method="relative")
#' @export #' @export
#' #'
#' @importFrom grDevices col2rgb
#' #'
contrast_text <- function(background, contrast_text <- function(background,
light_text = 'white', light_text = 'white',
@ -361,17 +323,20 @@ sentence_paste <- function(data, and.str = "and") {
#' @export #' @export
#' #'
#' @importFrom htmltools tagList tags css #' @importFrom htmltools tagList tags css
#' @importFrom shiny NS textInput textAreaInput uiOutput actionButton
#' @importFrom phosphoricons ph
#' @importFrom shinyWidgets virtualSelectInput
#' #'
#' @name create-column #' @name create-column
#' #'
#' @example examples/create_column_module_demo.R #' @example examples/create_column_module_demo.R
create_column_ui <- function(id) { create_column_ui <- function(id) {
ns <- NS(id) ns <- NS(id)
htmltools::tagList( tagList(
# datamods:::html_dependency_datamods(), # datamods:::html_dependency_datamods(),
# html_dependency_FreesearchR(), # html_dependency_FreesearchR(),
shiny::tags$head( tags$head(
shiny::tags$link(rel = "stylesheet", type = "text/css", href = "FreesearchR/inst/assets/css/FreesearchR.css") tags$link(rel = "stylesheet", type = "text/css", href = "FreesearchR/inst/assets/css/FreesearchR.css")
), ),
# tags$head( # tags$head(
# # Note the wrapping of the string in HTML() # # Note the wrapping of the string in HTML()
@ -425,7 +390,7 @@ create_column_ui <- function(id) {
) )
) )
), ),
shiny::textAreaInput( textAreaInput(
inputId = ns("expression"), inputId = ns("expression"),
label = i18n("Enter an expression to define new column:"), label = i18n("Enter an expression to define new column:"),
value = "", value = "",
@ -473,6 +438,9 @@ create_column_ui <- function(id) {
#' #'
#' @rdname create-column #' @rdname create-column
#' #'
#' @importFrom shiny moduleServer reactiveValues observeEvent renderUI req
#' updateTextAreaInput reactive bindEvent observe
#' @importFrom shinyWidgets alert updateVirtualSelect
create_column_server <- function(id, create_column_server <- function(id,
data_r = reactive(NULL), data_r = reactive(NULL),
allowed_operations = list_allowed_operations()) { allowed_operations = list_allowed_operations()) {
@ -979,6 +947,12 @@ vectorSelectInput <- function(inputId,
#### Current file: /Users/au301842/FreesearchR/R//cut-variable-dates.R #### Current file: /Users/au301842/FreesearchR/R//cut-variable-dates.R
######## ########
library(datamods)
library(toastui)
library(phosphoricons)
library(rlang)
library(shiny)
#' Extended cutting function with fall-back to the native base::cut #' Extended cutting function with fall-back to the native base::cut
#' #'
#' @param x an object inheriting from class "hms" #' @param x an object inheriting from class "hms"
@ -1187,9 +1161,9 @@ cut_variable_ui <- function(id) {
shiny::fluidRow( shiny::fluidRow(
column( column(
width = 3, width = 3,
shinyWidgets::virtualSelectInput( virtualSelectInput(
inputId = ns("variable"), inputId = ns("variable"),
label = datamods:::i18n("Variable to cut:"), label = i18n("Variable to cut:"),
choices = NULL, choices = NULL,
width = "100%" width = "100%"
) )
@ -1202,7 +1176,7 @@ cut_variable_ui <- function(id) {
width = 3, width = 3,
numericInput( numericInput(
inputId = ns("n_breaks"), inputId = ns("n_breaks"),
label = datamods:::i18n("Number of breaks:"), label = i18n("Number of breaks:"),
value = 3, value = 3,
min = 2, min = 2,
max = 12, max = 12,
@ -1213,12 +1187,12 @@ cut_variable_ui <- function(id) {
width = 3, width = 3,
checkboxInput( checkboxInput(
inputId = ns("right"), inputId = ns("right"),
label = datamods:::i18n("Close intervals on the right"), label = i18n("Close intervals on the right"),
value = TRUE value = TRUE
), ),
checkboxInput( checkboxInput(
inputId = ns("include_lowest"), inputId = ns("include_lowest"),
label = datamods:::i18n("Include lowest value"), label = i18n("Include lowest value"),
value = TRUE value = TRUE
) )
) )
@ -1229,10 +1203,10 @@ cut_variable_ui <- function(id) {
uiOutput(outputId = ns("slider_fixed")) uiOutput(outputId = ns("slider_fixed"))
), ),
plotOutput(outputId = ns("plot"), width = "100%", height = "270px"), plotOutput(outputId = ns("plot"), width = "100%", height = "270px"),
toastui::datagridOutput2(outputId = ns("count")), datagridOutput2(outputId = ns("count")),
actionButton( actionButton(
inputId = ns("create"), inputId = ns("create"),
label = tagList(phosphoricons::ph("scissors"), datamods:::i18n("Create factor variable")), label = tagList(ph("scissors"), i18n("Create factor variable")),
class = "btn-outline-primary float-end" class = "btn-outline-primary float-end"
), ),
tags$div(class = "clearfix") tags$div(class = "clearfix")
@ -1263,7 +1237,7 @@ cut_variable_server <- function(id, data_r = reactive(NULL)) {
is.numeric(.x) || is_datetime(.x) is.numeric(.x) || is_datetime(.x)
}, logical(1)) }, logical(1))
vars_num <- names(vars_num)[vars_num] vars_num <- names(vars_num)[vars_num]
shinyWidgets::updateVirtualSelect( updateVirtualSelect(
inputId = "variable", inputId = "variable",
choices = vars_num, choices = vars_num,
selected = if (isTruthy(input$variable)) input$variable else vars_num[1] selected = if (isTruthy(input$variable)) input$variable else vars_num[1]
@ -1300,9 +1274,9 @@ cut_variable_server <- function(id, data_r = reactive(NULL)) {
} }
shinyWidgets::noUiSliderInput( noUiSliderInput(
inputId = session$ns("fixed_brks"), inputId = session$ns("fixed_brks"),
label = datamods:::i18n("Fixed breaks:"), label = i18n("Fixed breaks:"),
min = lower, min = lower,
max = upper, max = upper,
value = brks, value = brks,
@ -1357,7 +1331,7 @@ cut_variable_server <- function(id, data_r = reactive(NULL)) {
shinyWidgets::virtualSelectInput( shinyWidgets::virtualSelectInput(
inputId = session$ns("method"), inputId = session$ns("method"),
label = datamods:::i18n("Method:"), label = i18n("Method:"),
choices = choices, choices = choices,
selected = NULL, selected = NULL,
width = "100%" width = "100%"
@ -1500,7 +1474,7 @@ cut_variable_server <- function(id, data_r = reactive(NULL)) {
data data
}) })
output$count <- toastui::renderDatagrid2({ output$count <- renderDatagrid2({
# shiny::req(rv$new_var_name) # shiny::req(rv$new_var_name)
data <- req(data_cutted_r()) data <- req(data_cutted_r())
# variable <- req(input$variable) # variable <- req(input$variable)
@ -1516,14 +1490,14 @@ cut_variable_server <- function(id, data_r = reactive(NULL)) {
datamods:::apply_grid_theme() datamods:::apply_grid_theme()
} }
on.exit(toastui::reset_grid_theme()) on.exit(toastui::reset_grid_theme())
grid <- toastui::datagrid( grid <- datagrid(
data = count_data, data = count_data,
colwidths = "guess", colwidths = "guess",
theme = "default", theme = "default",
bodyHeight = "auto" bodyHeight = "auto"
) )
grid <- toastui::grid_columns(grid, className = "font-monospace") grid <- toastui::grid_columns(grid, className = "font-monospace")
toastui::grid_colorbar( grid_colorbar(
grid, grid,
column = "count", column = "count",
label_outside = TRUE, label_outside = TRUE,
@ -1551,7 +1525,7 @@ cut_variable_server <- function(id, data_r = reactive(NULL)) {
#' #'
#' @rdname cut-variable #' @rdname cut-variable
modal_cut_variable <- function(id, modal_cut_variable <- function(id,
title = datamods:::i18n("Convert Numeric to Factor"), title = i18n("Convert Numeric to Factor"),
easyClose = TRUE, easyClose = TRUE,
size = "l", size = "l",
footer = NULL) { footer = NULL) {
@ -2281,7 +2255,6 @@ create_plot <- function(data, type, pri, sec, ter = NULL, ...) {
#' mtcars |> get_label() #' mtcars |> get_label()
#' mtcars$mpg |> get_label() #' mtcars$mpg |> get_label()
#' gtsummary::trial |> get_label(var = "trt") #' gtsummary::trial |> get_label(var = "trt")
#' gtsummary::trial$trt |> get_label()
#' 1:10 |> get_label() #' 1:10 |> get_label()
get_label <- function(data, var = NULL) { get_label <- function(data, var = NULL) {
# data <- if (is.reactive(data)) data() else data # data <- if (is.reactive(data)) data() else data
@ -3010,7 +2983,7 @@ show_data <- function(data,
if (is.null(options)) if (is.null(options))
options <- list() options <- list()
options$height <- 500 options$height <- 550
options$minBodyHeight <- 400 options$minBodyHeight <- 400
options$data <- data options$data <- data
options$theme <- "default" options$theme <- "default"
@ -3978,25 +3951,11 @@ is_identical_to_previous <- function(data, no.name = TRUE) {
} }
#' Simplified version of the snakecase packages to_snake_case
#'
#' @param data character string vector
#'
#' @returns vector
#' @export
#'
#' @examples
#' c("foo bar", "fooBar21", "!!Foo'B'a-r", "foo_bar", "F OO bar") |> simple_snake()
simple_snake <- function(data){
gsub("[\\s+]","_",gsub("[^\\w\\s:-]", "", tolower(data), perl=TRUE), perl=TRUE)
}
######## ########
#### Current file: /Users/au301842/FreesearchR/R//hosted_version.R #### Current file: /Users/au301842/FreesearchR/R//hosted_version.R
######## ########
hosted_version <- function()'v25.5.3-250510' hosted_version <- function()'v25.5.2-250508'
######## ########
@ -4834,11 +4793,10 @@ plot_euler <- function(data, pri, sec, ter = NULL, seed = 2103) {
out <- lapply(ds, \(.x){ out <- lapply(ds, \(.x){
.x[c(pri, sec)] |> .x[c(pri, sec)] |>
as.data.frame() |> as.data.frame() |>
na.omit() |>
plot_euler_single() plot_euler_single()
}) })
# names(out) # names(out)
wrap_plot_list(out) wrap_plot_list(out)
# patchwork::wrap_plots(out, guides = "collect") # patchwork::wrap_plots(out, guides = "collect")
} }
@ -4950,8 +4908,9 @@ vertical_stacked_bars <- function(data,
contrast_cut <- contrast_cut <-
sum(contrast_text(colors, threshold = .3) == "white") sum(contrast_text(colors, threshold = .3) == "white")
score_label <- data |> get_label(var = score) score_label <- ifelse(is.na(REDCapCAST::get_attr(data$score, "label")), score, REDCapCAST::get_attr(data$score, "label"))
group_label <- data |> get_label(var = group) group_label <- ifelse(is.na(REDCapCAST::get_attr(data$group, "label")), group, REDCapCAST::get_attr(data$group, "label"))
p |> p |>
(\(.x){ (\(.x){
@ -5141,6 +5100,7 @@ plot_sankey <- function(data, pri, sec, ter = NULL, color.group = "pri", colors
#' plot_sankey_single("first", "last", color.group = "pri") #' plot_sankey_single("first", "last", color.group = "pri")
#' mtcars |> #' mtcars |>
#' default_parsing() |> #' default_parsing() |>
#' str()
#' plot_sankey_single("cyl", "vs", color.group = "pri") #' plot_sankey_single("cyl", "vs", color.group = "pri")
plot_sankey_single <- function(data, pri, sec, color.group = c("pri", "sec"), colors = NULL, ...) { plot_sankey_single <- function(data, pri, sec, color.group = c("pri", "sec"), colors = NULL, ...) {
color.group <- match.arg(color.group) color.group <- match.arg(color.group)
@ -5153,6 +5113,8 @@ plot_sankey_single <- function(data, pri, sec, color.group = c("pri", "sec"), co
data <- data |> sankey_ready(pri = pri, sec = sec, ...) data <- data |> sankey_ready(pri = pri, sec = sec, ...)
library(ggalluvial)
na.color <- "#2986cc" na.color <- "#2986cc"
box.color <- "#1E4B66" box.color <- "#1E4B66"
@ -5216,8 +5178,6 @@ plot_sankey_single <- function(data, pri, sec, color.group = c("pri", "sec"), co
) )
} }
## Will fail to use stat="stratum" if library is not loaded.
library(ggalluvial)
p + p +
ggplot2::geom_text( ggplot2::geom_text(
stat = "stratum", stat = "stratum",
@ -5606,12 +5566,9 @@ m_redcap_readServer <- function(id) {
) )
# browser() # browser()
shiny::withProgress( shiny::withProgress({
{ imported <- try(rlang::exec(REDCapR::redcap_metadata_read, !!!parameters), silent = TRUE)
imported <- try(rlang::exec(REDCapR::redcap_metadata_read, !!!parameters), silent = TRUE) },message = paste("Connecting to",data_rv$uri))
},
message = paste("Connecting to", data_rv$uri)
)
## TODO: Simplify error messages ## TODO: Simplify error messages
if (inherits(imported, "try-error") || NROW(imported) < 1 || ifelse(is.list(imported), !isTRUE(imported$success), FALSE)) { if (inherits(imported, "try-error") || NROW(imported) < 1 || ifelse(is.list(imported), !isTRUE(imported$success), FALSE)) {
@ -5637,7 +5594,7 @@ m_redcap_readServer <- function(id) {
status = "success", status = "success",
include_data_alert( include_data_alert(
see_data_text = "Click to see data dictionary", see_data_text = "Click to see data dictionary",
dataIdName = "see_dd", dataIdName = "see_data",
extra = tags$p( extra = tags$p(
tags$b(phosphoricons::ph("check", weight = "bold"), "Connected to server!"), tags$b(phosphoricons::ph("check", weight = "bold"), "Connected to server!"),
glue::glue("The {data_rv$info$project_title} project is loaded.") glue::glue("The {data_rv$info$project_title} project is loaded.")
@ -5663,8 +5620,8 @@ m_redcap_readServer <- function(id) {
output$connect_success <- shiny::reactive(identical(data_rv$dd_status, "success")) output$connect_success <- shiny::reactive(identical(data_rv$dd_status, "success"))
shiny::outputOptions(output, "connect_success", suspendWhenHidden = FALSE) shiny::outputOptions(output, "connect_success", suspendWhenHidden = FALSE)
shiny::observeEvent(input$see_dd, { shiny::observeEvent(input$see_data, {
show_data( datamods::show_data(
purrr::pluck(data_rv$dd_list, "data"), purrr::pluck(data_rv$dd_list, "data"),
title = "Data dictionary", title = "Data dictionary",
type = "modal", type = "modal",
@ -5673,17 +5630,6 @@ m_redcap_readServer <- function(id) {
) )
}) })
shiny::observeEvent(input$see_data, {
show_data(
# purrr::pluck(data_rv$dd_list, "data"),
data_rv$data,
title = "Imported data set",
type = "modal",
show_classes = FALSE,
tags$b("Preview:")
)
})
arms <- shiny::reactive({ arms <- shiny::reactive({
shiny::req(input$api) shiny::req(input$api)
shiny::req(data_rv$uri) shiny::req(data_rv$uri)
@ -5798,24 +5744,13 @@ m_redcap_readServer <- function(id) {
imported <- try(rlang::exec(REDCapCAST::read_redcap_tables, !!!parameters), silent = TRUE) imported <- try(rlang::exec(REDCapCAST::read_redcap_tables, !!!parameters), silent = TRUE)
}) })
parameters_code <- parameters[c("uri", "fields", "events", "raw_or_label", "filter_logic")] code <- rlang::call2("read_redcap_tables",
!!!utils::modifyList(parameters, list(token = "PERSONAL_API_TOKEN")), ,
code <- rlang::call2(
"easy_redcap",
!!!utils::modifyList(
parameters_code,
list(
data_format = ifelse(
input$data_type == "long" && !is.null(input$data_type),
"long",
"wide"
),
project.name = simple_snake(data_rv$info$project_title)
)
),
.ns = "REDCapCAST" .ns = "REDCapCAST"
) )
# browser()
if (inherits(imported, "try-error") || NROW(imported) < 1) { if (inherits(imported, "try-error") || NROW(imported) < 1) {
data_rv$data_status <- "error" data_rv$data_status <- "error"
data_rv$data_list <- NULL data_rv$data_list <- NULL
@ -5884,17 +5819,9 @@ m_redcap_readServer <- function(id) {
datamods:::insert_alert( datamods:::insert_alert(
selector = ns("retrieved"), selector = ns("retrieved"),
status = data_rv$data_status, status = data_rv$data_status,
# tags$p( tags$p(
# tags$b(phosphoricons::ph("check", weight = "bold"), "Success!"), tags$b(phosphoricons::ph("check", weight = "bold"), "Success!"),
# data_rv$data_message data_rv$data_message
# ),
include_data_alert(
see_data_text = "Click to see the imported data",
dataIdName = "see_data",
extra = tags$p(
tags$b(phosphoricons::ph("check", weight = "bold"), data_rv$data_message)
),
btn_show_data = TRUE
) )
) )
} else { } else {
@ -6095,6 +6022,13 @@ redcap_demo_app <- function() {
} }
########
#### Current file: /Users/au301842/FreesearchR/R//redcap.R
########
######## ########
#### Current file: /Users/au301842/FreesearchR/R//regression_model.R #### Current file: /Users/au301842/FreesearchR/R//regression_model.R
######## ########
@ -6372,13 +6306,12 @@ data_type <- function(data) {
sapply(data, data_type) sapply(data, data_type)
} else { } else {
cl_d <- class(data) cl_d <- class(data)
l_unique <- length(unique(na.omit(data)))
if (all(is.na(data))) { if (all(is.na(data))) {
out <- "empty" out <- "empty"
} else if (l_unique < 2) { } else if (length(unique(data)) < 2) {
out <- "monotone" out <- "monotone"
} else if (any(c("factor", "logical") %in% cl_d) | l_unique == 2) { } else if (any(c("factor", "logical") %in% cl_d) | length(unique(data)) == 2) {
if (identical("logical", cl_d) | l_unique == 2) { if (identical("logical", cl_d) | length(unique(data)) == 2) {
out <- "dichotomous" out <- "dichotomous"
} else { } else {
# if (is.ordered(data)) { # if (is.ordered(data)) {
@ -6391,7 +6324,7 @@ data_type <- function(data) {
out <- "text" out <- "text"
} else if (any(c("hms", "Date", "POSIXct", "POSIXt") %in% cl_d)) { } else if (any(c("hms", "Date", "POSIXct", "POSIXt") %in% cl_d)) {
out <- "datetime" out <- "datetime"
} else if (l_unique > 2) { } else if (!length(unique(data)) == 2) {
## Previously had all thinkable classes ## Previously had all thinkable classes
## Now just assumes the class has not been defined above ## Now just assumes the class has not been defined above
## any(c("numeric", "integer", "hms", "Date", "timediff") %in% cl_d) & ## any(c("numeric", "integer", "hms", "Date", "timediff") %in% cl_d) &
@ -8066,7 +7999,7 @@ update_factor_ui <- function(id) {
fluidRow( fluidRow(
column( column(
width = 6, width = 6,
shinyWidgets::virtualSelectInput( virtualSelectInput(
inputId = ns("variable"), inputId = ns("variable"),
label = i18n("Factor variable to reorder:"), label = i18n("Factor variable to reorder:"),
choices = NULL, choices = NULL,
@ -8101,10 +8034,10 @@ update_factor_ui <- function(id) {
) )
) )
), ),
toastui::datagridOutput(ns("grid")), datagridOutput(ns("grid")),
tags$div( tags$div(
class = "float-end", class = "float-end",
shinyWidgets::prettyCheckbox( prettyCheckbox(
inputId = ns("new_var"), inputId = ns("new_var"),
label = i18n("Create a new variable (otherwise replaces the one selected)"), label = i18n("Create a new variable (otherwise replaces the one selected)"),
value = FALSE, value = FALSE,
@ -8330,6 +8263,10 @@ winbox_update_factor <- function(id,
#### Current file: /Users/au301842/FreesearchR/R//update-variables-ext.R #### Current file: /Users/au301842/FreesearchR/R//update-variables-ext.R
######## ########
library(data.table)
library(rlang)
#' Select, rename and convert variables #' Select, rename and convert variables
#' #'
#' @param id Module id. See [shiny::moduleServer()]. #' @param id Module id. See [shiny::moduleServer()].
@ -9380,10 +9317,10 @@ ui_elements <- list(
condition = "input.source=='env'", condition = "input.source=='env'",
import_globalenv_ui(id = "env", title = NULL) import_globalenv_ui(id = "env", title = NULL)
), ),
# shiny::conditionalPanel( shiny::conditionalPanel(
# condition = "input.source=='redcap'", condition = "input.source=='redcap'",
# DT::DTOutput(outputId = "redcap_prev") DT::DTOutput(outputId = "redcap_prev")
# ), ),
shiny::conditionalPanel( shiny::conditionalPanel(
condition = "output.data_loaded == true", condition = "output.data_loaded == true",
shiny::br(), shiny::br(),
@ -9392,8 +9329,13 @@ ui_elements <- list(
shiny::fluidRow( shiny::fluidRow(
shiny::column( shiny::column(
width = 6, width = 6,
shiny::p("Filter by completeness threshold:"),
shiny::br(), shiny::br(),
shiny::p("Filter by completeness threshold and manual selection:"),
shiny::br(),
shiny::br()
),
shiny::column(
width = 6,
shinyWidgets::noUiSliderInput( shinyWidgets::noUiSliderInput(
inputId = "complete_cutoff", inputId = "complete_cutoff",
label = NULL, label = NULL,
@ -9406,17 +9348,12 @@ ui_elements <- list(
color = datamods:::get_primary_color() color = datamods:::get_primary_color()
), ),
shiny::helpText("Exclude variables with completeness below the specified percentage."), shiny::helpText("Exclude variables with completeness below the specified percentage."),
shiny::br() shiny::br(),
),
shiny::column(
width = 6,
shiny::p("Specify manually:"),
shiny::br(), shiny::br(),
shiny::uiOutput(outputId = "import_var"), shiny::uiOutput(outputId = "import_var"),
shiny::br() shiny::uiOutput(outputId = "data_info_import", inline = TRUE)
) )
), )
shiny::uiOutput(outputId = "data_info_import", inline = TRUE)
), ),
shiny::br(), shiny::br(),
shiny::br(), shiny::br(),
@ -9893,7 +9830,33 @@ ui <- bslib::page_fixed(
#### Current file: /Users/au301842/FreesearchR/app/server.R #### Current file: /Users/au301842/FreesearchR/app/server.R
######## ########
library(readr)
library(MASS)
library(stats)
library(gt)
# library(openxlsx2)
library(haven)
library(readODS)
require(shiny)
library(bslib)
library(assertthat)
library(dplyr)
library(quarto)
library(here)
library(broom)
library(broom.helpers)
library(easystats)
library(patchwork)
library(DHARMa)
library(apexcharter)
library(toastui)
library(datamods)
library(IDEAFilter)
library(shinyWidgets)
library(DT)
library(data.table)
library(gtsummary)
library(shinyjs)
data(starwars) data(starwars)
data(mtcars) data(mtcars)
@ -9901,8 +9864,8 @@ data(trial)
load_data <- function() { load_data <- function() {
Sys.sleep(1) Sys.sleep(1)
shinyjs::hide("loading_page") hide("loading_page")
shinyjs::show("main_content") show("main_content")
} }
@ -9983,14 +9946,14 @@ server <- function(input, output, session) {
}) })
## This is used to ensure the reactive data is retrieved ## This is used to ensure the reactive data is retrieved
# output$redcap_prev <- DT::renderDT( output$redcap_prev <- DT::renderDT(
# { {
# DT::datatable(head(from_redcap$data(), 5), DT::datatable(head(from_redcap$data(), 5),
# caption = "First 5 observations" caption = "First 5 observations"
# ) )
# }, },
# server = TRUE server = TRUE
# ) )
from_env <- datamods::import_globalenv_server( from_env <- datamods::import_globalenv_server(
id = "env", id = "env",

View file

@ -13,7 +13,7 @@ cut_variable_server(id, data_r = reactive(NULL))
modal_cut_variable( modal_cut_variable(
id, id,
title = datamods:::i18n("Convert Numeric to Factor"), title = i18n("Convert Numeric to Factor"),
easyClose = TRUE, easyClose = TRUE,
size = "l", size = "l",
footer = NULL footer = NULL

View file

@ -22,6 +22,5 @@ mtcars |> get_label(var = "mpg")
mtcars |> get_label() mtcars |> get_label()
mtcars$mpg |> get_label() mtcars$mpg |> get_label()
gtsummary::trial |> get_label(var = "trt") gtsummary::trial |> get_label(var = "trt")
gtsummary::trial$trt |> get_label()
1:10 |> get_label() 1:10 |> get_label()
} }

View file

@ -39,5 +39,6 @@ data.frame(
plot_sankey_single("first", "last", color.group = "pri") plot_sankey_single("first", "last", color.group = "pri")
mtcars |> mtcars |>
default_parsing() |> default_parsing() |>
str()
plot_sankey_single("cyl", "vs", color.group = "pri") plot_sankey_single("cyl", "vs", color.group = "pri")
} }

View file

@ -1,20 +0,0 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/helpers.R
\name{simple_snake}
\alias{simple_snake}
\title{Simplified version of the snakecase packages to_snake_case}
\usage{
simple_snake(data)
}
\arguments{
\item{data}{character string vector}
}
\value{
vector
}
\description{
Simplified version of the snakecase packages to_snake_case
}
\examples{
c("foo bar", "fooBar21", "!!Foo'B'a-r", "foo_bar", "F OO bar") |> simple_snake()
}