"` (or `"i18n"` if no package) to returns appropriate labels.
#'
#' @export
#'
#' @rdname i18n
#'
#' @importFrom utils packageName
#' @importFrom data.table fread
i18n_translations <- function(package = packageName(parent.frame(2))) {
if (is.null(package)) {
opts <- "i18n"
} else {
opts <- paste(package, "i18n", sep = ".")
}
language <- getOption(x = opts)
if (is.null(language))
return(NULL)
if (is.character(language) && i18n_exist(language, package = package)) {
language <- fread(file = i18n_file(language, package = package), encoding = "UTF-8", fill = TRUE)
} else if (is.character(language) && file.exists(language)) {
language <- fread(file = language, encoding = "UTF-8", fill = TRUE)
} else if (is.character(language)) {
warning(
"i18n translations not found for : ", language,
call. = FALSE
)
language <- NULL
}
return(language)
}
#' @param value Value to set for translation. Can be:
#' * single `character` to use a supported language (`"fr"`, `"mk"`, `"al"`, `"pt"` for esquisse and datamods packages).
#' * a `list` with labels as names and translations as values.
#' * a `data.frame` with 2 column: `label` & `translation`.
#' * path to a CSV file with same structure as for `data.frame` above.
#' @param packages Name of packages for which to set i18n, default to esquisse and datamods
#'
#' @export
#'
#' @rdname i18n
#'
#' @importFrom stats setNames
set_i18n <- function(value, packages = c("datamods", "esquisse")) {
if (is.null(packages)) {
options("i18n" = value)
} else {
i18n.opts <- setNames(
lapply(seq_along(packages), function(...) value),
paste(packages, "i18n", sep = ".")
)
options(i18n.opts)
}
}
i18n_file <- function(x, package) {
if (is.null(package))
return(character(0))
system.file("i18n", paste0(x, ".csv"), package = package)
}
i18n_exist <- function(x, package) {
isTRUE(file.exists(i18n_file(x, package)))
}
i18n_test <- function(x) {
i18n(x)
}
================================================
FILE: R/import-copypaste.R
================================================
#' @title Import data with copy & paste
#'
#' @description Let the user copy data from Excel or text file then paste it into a text area to import it.
#'
#' @inheritParams import-globalenv
#' @param name_field Show or not a field to add a name to data (that is returned server-side).
#'
#' @template module-import
#'
#' @export
#'
#' @name import-copypaste
#'
#' @importFrom shiny NS icon textAreaInput actionButton textInput
#' @importFrom htmltools tags tagAppendAttributes
#'
#' @example examples/from-copypaste.R
import_copypaste_ui <- function(id, title = TRUE, name_field = TRUE) {
ns <- NS(id)
if (isTRUE(title)) {
title <- tags$h4(
i18n("Copy & paste data"),
class = "datamods-title"
)
}
tags$div(
class = "datamods-import",
html_dependency_datamods(),
title,
tagAppendAttributes(
textAreaInput(
inputId = ns("data_pasted"),
label = i18n("Paste data here:"),
height = "300px",
width = "100%",
resize = "none"
),
class = "shiny-input-container-inline"
),
if (isTRUE(name_field)) {
textInput(
inputId = ns("name"),
label = NULL,
placeholder = i18n("Add a label to data"),
width = "100%"
)
},
tags$div(
id = ns("import-placeholder"),
alert(
id = ns("import-result"),
status = "info",
tags$b(i18n("Nothing pasted yet!")),
i18n("Please copy and paste some data in the dialog box above."),
dismissible = TRUE
)
),
uiOutput(
outputId = ns("container_valid_btn"),
style = "margin-top: 20px;"
)
)
}
#' @inheritParams import_globalenv_server
#' @param fread_args `list` of additional arguments to pass to [data.table::fread()] when reading data.
#'
#' @export
#'
#' @importFrom shiny moduleServer
#' @importFrom data.table fread
#' @importFrom shiny reactiveValues observeEvent removeUI reactive
#' @importFrom htmltools tags tagList
#' @importFrom rlang %||%
#'
#' @rdname import-copypaste
import_copypaste_server <- function(id,
btn_show_data = TRUE,
show_data_in = c("popup", "modal"),
trigger_return = c("button", "change"),
return_class = c("data.frame", "data.table", "tbl_df", "raw"),
reset = reactive(NULL),
fread_args = list()) {
trigger_return <- match.arg(trigger_return)
return_class <- match.arg(return_class)
module <- function(input, output, session) {
ns <- session$ns
imported_rv <- reactiveValues(data = NULL, name = NULL)
temporary_rv <- reactiveValues(data = NULL, name = NULL, status = NULL)
observeEvent(reset(), {
temporary_rv$data <- NULL
temporary_rv$name <- NULL
temporary_rv$status <- NULL
})
output$container_valid_btn <- renderUI({
if (identical(trigger_return, "button")) {
button_import()
}
})
observeEvent(input$data_pasted, {
req(input$data_pasted)
fread_args$tex <- input$data_pasted
imported <- try(rlang::exec(data.table::fread, !!!fread_args), silent = TRUE)
if (inherits(imported, "try-error") || NROW(imported) < 1) {
toggle_widget(inputId = "confirm", enable = FALSE)
insert_error(mssg = i18n(attr(imported, "condition")$message))
temporary_rv$status <- "error"
temporary_rv$data <- NULL
temporary_rv$name <- NULL
} else {
toggle_widget(inputId = "confirm", enable = TRUE)
insert_alert(
selector = ns("import"),
status = "success",
make_success_alert(
imported,
trigger_return = trigger_return,
btn_show_data = btn_show_data
)
)
temporary_rv$status <- "success"
temporary_rv$data <- imported
}
}, ignoreInit = TRUE)
observeEvent(input$name, {
temporary_rv$name <- if (isTruthy(input$name)) {
input$name
} else {
"clipboard_data"
}
})
observeEvent(input$see_data, {
show_data(temporary_rv$data, title = i18n("Imported data"), type = show_data_in)
})
observeEvent(input$confirm, {
imported_rv$data <- temporary_rv$data
imported_rv$name <- temporary_rv$name
})
if (identical(trigger_return, "button")) {
return(list(
status = reactive(temporary_rv$status),
name = reactive(imported_rv$name),
data = reactive(as_out(imported_rv$data, return_class))
))
} else {
return(list(
status = reactive(temporary_rv$status),
name = reactive(temporary_rv$name),
data = reactive(as_out(temporary_rv$data, return_class))
))
}
}
moduleServer(
id = id,
module = module
)
}
================================================
FILE: R/import-file.R
================================================
#' @title Import data from a file
#'
#' @description Let user upload a file and import data
#'
#' @inheritParams import-globalenv
#' @param preview_data Show or not a preview of the data under the file input.
#' @param file_extensions File extensions accepted by [shiny::fileInput()], can also be MIME type.
#' @param layout_params How to display import parameters : in a dropdown button or inline below file input.
#'
#' @template module-import
#'
#' @export
#'
#' @name import-file
#'
#' @importFrom shiny NS fileInput actionButton icon
#' @importFrom htmltools tags tagAppendAttributes css tagAppendChild
#' @importFrom shinyWidgets pickerInput numericInputIcon textInputIcon dropMenu
#' @importFrom phosphoricons ph
#' @importFrom toastui datagridOutput2
#'
#' @example examples/from-file.R
import_file_ui <- function(id,
title = TRUE,
preview_data = TRUE,
file_extensions = c(".csv", ".txt", ".xls", ".xlsx", ".rds", ".fst", ".sas7bdat", ".sav"),
layout_params = c("dropdown", "inline")) {
ns <- NS(id)
if (!is.null(layout_params)) {
layout_params <- match.arg(layout_params)
}
if (isTRUE(title)) {
title <- tags$h4(
i18n("Import a file"),
class = "datamods-title"
)
}
params_ui <- fluidRow(
column(
width = 6,
numericInputIcon(
inputId = ns("skip_rows"),
label = i18n("Rows to skip before reading data:"),
value = 0,
min = 0,
icon = list("n ="),
size = "sm",
width = "100%"
),
tagAppendChild(
textInputIcon(
inputId = ns("na_label"),
label = i18n("Missing values character(s):"),
value = ",NA",
icon = list("NA"),
size = "sm",
width = "100%"
),
shiny::helpText(ph("info"), i18n("if several use a comma (',') to separate them"))
)
),
column(
width = 6,
textInputIcon(
inputId = ns("dec"),
label = i18n("Decimal separator:"),
value = ".",
icon = list("0.00"),
size = "sm",
width = "100%"
),
textInputIcon(
inputId = ns("encoding"),
label = i18n("Encoding:"),
value = "UTF-8",
icon = phosphoricons::ph("text-aa"),
size = "sm",
width = "100%"
)
)
)
file_ui <- tagAppendAttributes(
fileInput(
inputId = ns("file"),
label = i18n("Upload a file:"),
buttonLabel = i18n("Browse..."),
placeholder = i18n("No file selected"),
accept = file_extensions,
width = "100%"
),
class = "mb-0"
)
if (identical(layout_params, "dropdown")) {
file_ui <- tags$div(
style = css(
display = "grid",
gridTemplateColumns = "1fr 50px",
gridColumnGap = "10px"
),
file_ui,
tags$div(
class = "shiny-input-container",
tags$label(
class = "control-label",
`for` = ns("dropdown_params"),
"...",
style = css(visibility = "hidden")
),
shinyWidgets::dropMenu(
actionButton(
inputId = ns("dropdown_params"),
label = ph("gear", title = "Parameters"),
width = "50px",
class = "px-1"
),
params_ui
)
)
)
}
tags$div(
class = "datamods-import",
html_dependency_datamods(),
shinyWidgets::html_dependency_winbox(),
title,
file_ui,
if (identical(layout_params, "inline")) params_ui,
tags$div(
class = "hidden",
id = ns("sheet-container"),
pickerInput(
inputId = ns("sheet"),
label = i18n("Select sheet to import:"),
choices = NULL,
width = "100%"
)
),
tags$div(
id = ns("import-placeholder"),
alert(
id = ns("import-result"),
status = "info",
tags$b(i18n("No file selected:")),
sprintf(i18n("You can import %s files"), paste(file_extensions, collapse = ", ")),
dismissible = TRUE
)
),
if (isTRUE(preview_data)) {
datagridOutput2(outputId = ns("table"))
},
uiOutput(
outputId = ns("container_confirm_btn"),
style = "margin-top: 20px;"
),
tags$div(
style = css(display = "none"),
checkboxInput(
inputId = ns("preview_data"),
label = NULL,
value = isTRUE(preview_data)
)
)
)
}
#' @inheritParams import_globalenv_server
#' @param read_fns Named list with custom function(s) to read data:
#' * the name must be the extension of the files to which the function will be applied
#' * the value must be a function that can have 5 arguments (you can ignore some of them, but you have to use the same names),
#' passed by user through the interface:
#' + `file`: path to the file
#' + `sheet`: for Excel files, sheet to read
#' + `skip`: number of row to skip
#' + `dec`: decimal separator
#' + `encoding`: file encoding
#' + `na.strings`: character(s) to interpret as missing values.
#'
#' @export
#'
#' @importFrom shiny moduleServer
#' @importFrom htmltools tags tagList
#' @importFrom shiny reactiveValues reactive observeEvent removeUI req
#' @importFrom shinyWidgets updatePickerInput
#' @importFrom readxl excel_sheets
#' @importFrom rio import
#' @importFrom rlang exec fn_fmls_names is_named is_function
#' @importFrom tools file_ext
#' @importFrom utils head
#' @importFrom toastui renderDatagrid2 datagrid
#'
#' @rdname import-file
import_file_server <- function(id,
btn_show_data = TRUE,
show_data_in = "winbox",
trigger_return = c("button", "change"),
return_class = c("data.frame", "data.table", "tbl_df", "raw"),
reset = reactive(NULL),
read_fns = list()) {
if (length(read_fns) > 0) {
if (!is_named(read_fns))
stop("import_file_server: `read_fns` must be a named list.", call. = FALSE)
if (!all(vapply(read_fns, is_function, logical(1))))
stop("import_file_server: `read_fns` must be list of function(s).", call. = FALSE)
}
trigger_return <- match.arg(trigger_return)
return_class <- match.arg(return_class)
module <- function(input, output, session) {
ns <- session$ns
imported_rv <- reactiveValues(data = NULL, name = NULL)
temporary_rv <- reactiveValues(data = NULL, name = NULL, status = NULL)
observeEvent(reset(), {
temporary_rv$data <- NULL
temporary_rv$name <- NULL
temporary_rv$status <- NULL
})
output$container_confirm_btn <- renderUI({
if (identical(trigger_return, "button")) {
button_import()
}
})
observeEvent(input$file, {
if (isTRUE(is_excel(input$file$datapath))) {
updatePickerInput(
session = session,
inputId = "sheet",
choices = readxl::excel_sheets(input$file$datapath)
)
showUI(paste0("#", ns("sheet-container")))
} else {
hideUI(paste0("#", ns("sheet-container")))
}
})
observeEvent(list(
input$file,
input$sheet,
input$skip_rows,
input$dec,
input$encoding,
input$na_label
), {
req(input$file)
# req(input$skip_rows)
extension <- tools::file_ext(input$file$datapath)
if (isTRUE(extension %in% names(read_fns))) {
parameters <- list(
file = input$file$datapath,
sheet = input$sheet,
skip = input$skip_rows,
dec = input$dec,
encoding = input$encoding,
na.strings = split_char(input$na_label)
)
parameters <- parameters[which(names(parameters) %in% fn_fmls_names(read_fns[[extension]]))]
imported <- try(rlang::exec(read_fns[[extension]], !!!parameters), silent = TRUE)
code <- call2(read_fns[[extension]], !!!modifyList(parameters, list(file = input$file$name)))
} else {
if (is_excel(input$file$datapath)) {
req(input$sheet)
parameters <- list(
file = input$file$datapath,
which = input$sheet,
skip = input$skip_rows,
na = split_char(input$na_label)
)
} else if (is_sas(input$file$datapath)) {
parameters <- list(
file = input$file$datapath,
skip = input$skip_rows,
encoding = input$encoding
)
} else {
parameters <- list(
file = input$file$datapath,
skip = input$skip_rows,
dec = input$dec,
encoding = input$encoding,
na.strings = split_char(input$na_label)
)
}
imported <- try(rlang::exec(rio::import, !!!parameters), silent = TRUE)
code <- call2("import", !!!modifyList(parameters, list(file = input$file$name)), .ns = "rio")
}
if (inherits(imported, "try-error")) {
imported <- try(rlang::exec(rio::import, !!!parameters[1]), silent = TRUE)
code <- call2("import", !!!list(file = input$file$name), .ns = "rio")
}
if (inherits(imported, "try-error") || NROW(imported) < 1) {
toggle_widget(inputId = "confirm", enable = FALSE)
insert_error(mssg = i18n(attr(imported, "condition")$message))
temporary_rv$status <- "error"
temporary_rv$data <- NULL
temporary_rv$name <- NULL
temporary_rv$code <- NULL
} else {
toggle_widget(inputId = "confirm", enable = TRUE)
insert_alert(
selector = ns("import"),
status = "success",
make_success_alert(
imported,
trigger_return = trigger_return,
btn_show_data = btn_show_data,
extra = if (isTRUE(input$preview_data)) i18n("First five rows are shown below:")
)
)
temporary_rv$status <- "success"
temporary_rv$data <- imported
temporary_rv$name <- input$file$name
temporary_rv$code <- code
}
}, ignoreInit = TRUE)
observeEvent(input$see_data, {
show_data(temporary_rv$data, title = i18n("Imported data"), type = show_data_in)
})
output$table <- renderDatagrid2({
req(temporary_rv$data)
datagrid(
data = head(temporary_rv$data, 5),
theme = "striped",
colwidths = "guess",
minBodyHeight = 250
)
})
observeEvent(input$confirm, {
imported_rv$data <- temporary_rv$data
imported_rv$name <- temporary_rv$name
imported_rv$code <- temporary_rv$code
})
if (identical(trigger_return, "button")) {
return(list(
status = reactive(temporary_rv$status),
name = reactive(imported_rv$name),
code = reactive(imported_rv$code),
data = reactive(as_out(imported_rv$data, return_class))
))
} else {
return(list(
status = reactive(temporary_rv$status),
name = reactive(temporary_rv$name),
code = reactive(temporary_rv$code),
data = reactive(as_out(temporary_rv$data, return_class))
))
}
}
moduleServer(
id = id,
module = module
)
}
# utils -------------------------------------------------------------------
is_excel <- function(path) {
isTRUE(tools::file_ext(path) %in% c("xls", "xlsx"))
}
is_sas <- function(path) {
isTRUE(tools::file_ext(path) %in% c("sas7bdat"))
}
================================================
FILE: R/import-globalenv.R
================================================
#' @title Import data from an Environment
#'
#' @description Let the user select a dataset from its own environment or from a package's environment.
#'
#' @param id Module's ID.
#' @param globalenv Search for data in Global environment.
#' @param packages Name of packages in which to search data.
#' @param title Module's title, if `TRUE` use the default title,
#' use `NULL` for no title or a `shiny.tag` for a custom one.
#'
#' @template module-import
#'
#' @export
#'
#' @name import-globalenv
#'
#' @importFrom htmltools tags
#' @importFrom shiny NS actionButton icon textInput
#' @importFrom shinyWidgets pickerInput alert
#'
#' @example examples/from-globalenv.R
import_globalenv_ui <- function(id,
globalenv = TRUE,
packages = get_data_packages(),
title = TRUE) {
ns <- NS(id)
choices <- list()
if (isTRUE(globalenv)) {
choices <- append(choices, "Global Environment")
}
if (!is.null(packages)) {
choices <- append(choices, list(Packages = as.character(packages)))
}
if (isTRUE(globalenv)) {
selected <- "Global Environment"
} else {
selected <- packages[1]
}
if (isTRUE(title)) {
title <- tags$h4(
i18n("Import a dataset from an environment"),
class = "datamods-title"
)
}
tags$div(
class = "datamods-import",
html_dependency_datamods(),
title,
pickerInput(
inputId = ns("data"),
label = i18n("Select a data.frame:"),
choices = NULL,
options = list(title = i18n("List of data.frame...")),
width = "100%"
),
pickerInput(
inputId = ns("env"),
label = i18n("Select an environment in which to search:"),
choices = choices,
selected = selected,
width = "100%",
options = list(
"title" = i18n("Select environment"),
"live-search" = TRUE,
"size" = 10
)
),
tags$div(
id = ns("import-placeholder"),
alert(
id = ns("import-result"),
status = "info",
tags$b(i18n("No data selected!")),
i18n("Use a data.frame from your environment or from the environment of a package."),
dismissible = TRUE
)
),
uiOutput(
outputId = ns("container_valid_btn"),
style = "margin-top: 20px;"
)
)
}
#' @param btn_show_data Display or not a button to display data in a modal window if import is successful.
#' @param show_data_in Where to display data: in a `"popup"` or in a `"modal"` window.
#' @param trigger_return When to update selected data:
#' `"button"` (when user click on button) or
#' `"change"` (each time user select a dataset in the list).
#' @param return_class Class of returned data: `data.frame`, `data.table`, `tbl_df` (tibble) or `raw`.
#' @param reset A `reactive` function that when triggered resets the data.
#'
#' @export
#'
#' @importFrom shiny moduleServer reactiveValues observeEvent reactive removeUI is.reactive icon actionLink isTruthy
#' @importFrom htmltools tags tagList
#' @importFrom shinyWidgets updatePickerInput
#'
#' @rdname import-globalenv
import_globalenv_server <- function(id,
btn_show_data = TRUE,
show_data_in = c("popup", "modal"),
trigger_return = c("button", "change"),
return_class = c("data.frame", "data.table", "tbl_df", "raw"),
reset = reactive(NULL)) {
trigger_return <- match.arg(trigger_return)
return_class <- match.arg(return_class)
module <- function(input, output, session) {
ns <- session$ns
imported_rv <- reactiveValues(data = NULL, name = NULL)
temporary_rv <- reactiveValues(data = NULL, name = NULL, status = NULL)
observeEvent(reset(), {
temporary_rv$data <- NULL
temporary_rv$name <- NULL
temporary_rv$status <- NULL
})
output$container_valid_btn <- renderUI({
if (identical(trigger_return, "button")) {
button_import()
}
})
observeEvent(input$env, {
if (identical(input$env, "Global Environment")) {
choices <- search_obj("data.frame")
} else {
choices <- list_pkg_data(input$env)
}
if (is.null(choices)) {
choices <- i18n("No data.frame here...")
choicesOpt <- list(disabled = TRUE)
} else {
choicesOpt <- list(
subtext = get_dimensions(choices)
)
}
temporary_rv$package <- attr(choices, "package")
updatePickerInput(
session = session,
inputId = "data",
choices = choices,
choicesOpt = choicesOpt
)
})
observeEvent(input$trigger, {
if (identical(trigger_return, "change")) {
hideUI(selector = paste0("#", ns("container_valid_btn")))
}
})
observeEvent(input$data, {
if (!isTruthy(input$data)) {
toggle_widget(inputId = "confirm", enable = FALSE)
insert_alert(
selector = ns("import"),
status = "info",
tags$b(i18n("No data selected!")),
i18n("Use a data.frame from your environment or from the environment of a package.")
)
} else {
name_df <- input$data
if (!is.null(temporary_rv$package)) {
attr(name_df, "package") <- temporary_rv$package
}
imported <- try(get_env_data(name_df), silent = TRUE)
if (inherits(imported, "try-error") || NROW(imported) < 1) {
toggle_widget(inputId = "confirm", enable = FALSE)
insert_error(mssg = i18n(attr(imported, "condition")$message))
temporary_rv$status <- "error"
temporary_rv$data <- NULL
temporary_rv$name <- NULL
} else {
toggle_widget(inputId = "confirm", enable = TRUE)
insert_alert(
selector = ns("import"),
status = "success",
make_success_alert(
imported,
trigger_return = trigger_return,
btn_show_data = btn_show_data
)
)
pkg <- attr(name_df, "package")
if (!is.null(pkg)) {
name <- paste(pkg, input$data, sep = "::")
} else {
name <- input$data
}
name <- trimws(sub("\\(([^\\)]+)\\)", "", name))
temporary_rv$status <- "success"
temporary_rv$data <- imported
temporary_rv$name <- name
}
}
}, ignoreInit = TRUE, ignoreNULL = FALSE)
observeEvent(input$see_data, {
show_data(temporary_rv$data, title = i18n("Imported data"), type = show_data_in)
})
observeEvent(input$confirm, {
imported_rv$data <- temporary_rv$data
imported_rv$name <- temporary_rv$name
})
if (identical(trigger_return, "button")) {
return(list(
status = reactive(temporary_rv$status),
name = reactive(imported_rv$name),
data = reactive(as_out(imported_rv$data, return_class))
))
} else {
return(list(
status = reactive(temporary_rv$status),
name = reactive(temporary_rv$name),
data = reactive(as_out(temporary_rv$data, return_class))
))
}
}
moduleServer(
id = id,
module = module
)
}
# utils -------------------------------------------------------------------
#' Get packages containing datasets
#'
#' @return a character vector of packages names
#' @export
#'
#' @importFrom utils data
#'
#' @examples
#' if (interactive()) {
#'
#' get_data_packages()
#'
#' }
get_data_packages <- function() {
suppressWarnings({
pkgs <- data(package = .packages(all.available = TRUE))
})
unique(pkgs$results[, 1])
}
#' List dataset contained in a package
#'
#' @param pkg Name of the package, must be installed.
#'
#' @return a \code{character} vector or \code{NULL}.
#' @export
#'
#' @importFrom utils data
#'
#' @examples
#'
#' list_pkg_data("ggplot2")
list_pkg_data <- function(pkg) {
if (isTRUE(requireNamespace(pkg, quietly = TRUE))) {
list_data <- data(package = pkg, envir = environment())$results[, "Item"]
list_data <- sort(list_data)
attr(list_data, "package") <- pkg
if (length(list_data) < 1) {
NULL
} else {
unname(list_data)
}
} else {
NULL
}
}
#' @importFrom utils data
get_env_data <- function(obj, env = globalenv()) {
pkg <- attr(obj, "package")
re <- regexpr(pattern = "\\(([^\\)]+)\\)", text = obj)
obj_ <- substr(x = obj, start = re + 1, stop = re + attr(re, "match.length") - 2)
obj <- gsub(pattern = "\\s.*", replacement = "", x = obj)
if (obj %in% ls(name = env)) {
get(x = obj, envir = env)
} else if (!is.null(pkg) && !identical(pkg, "")) {
res <- suppressWarnings(try(
get(utils::data(list = obj, package = pkg, envir = environment())), silent = TRUE
))
if (!inherits(res, "try-error"))
return(res)
data(list = obj_, package = pkg, envir = environment())
get(obj, envir = environment())
} else {
NULL
}
}
get_dimensions <- function(objs) {
if (is.null(objs))
return(NULL)
dataframes_dims <- Map(
f = function(name, pkg) {
attr(name, "package") <- pkg
tmp <- suppressWarnings(get_env_data(name))
if (is.data.frame(tmp)) {
sprintf("%d obs. of %d variables", nrow(tmp), ncol(tmp))
} else {
i18n("Not a data.frame")
}
},
name = objs,
pkg = if (!is.null(attr(objs, "package"))) {
attr(objs, "package")
} else {
character(1)
}
)
unlist(dataframes_dims)
}
================================================
FILE: R/import-googlesheets.R
================================================
#' @title Import data from Googlesheet
#'
#' @description Let user paste link to a Google sheet then import the data.
#'
#' @inheritParams import-globalenv
#'
#' @template module-import
#'
#' @export
#' @name import-googlesheets
#'
#' @importFrom shiny NS actionLink
#' @importFrom shinyWidgets textInputIcon
#' @importFrom htmltools tags tagList
#'
#' @example examples/from-googlesheets.R
import_googlesheets_ui <- function(id, title = TRUE) {
ns <- NS(id)
if (isTRUE(title)) {
title <- tags$h4(
i18n("Import Google Spreadsheet"),
class = "datamods-title"
)
}
tags$div(
class = "datamods-import",
html_dependency_datamods(),
title,
tags$div(
class = "pull-right float-right",
help_popup(tagList(
i18n("You can either use:"),
tags$ul(
tags$li(
i18n("A shareable link, in that case first sheet will be read")
),
tags$li(
i18n("The URL that appear in your browser, in that case the current sheet will be read")
)
)
))
),
textInputIcon(
inputId = ns("link"),
label = i18n("Enter a shareable link to a GoogleSheet:"),
icon = phosphoricons::ph("link"),
width = "100%"
),
tags$div(
id = ns("import-placeholder"),
alert(
id = ns("import-result"),
status = "info",
tags$b(i18n("Nothing pasted yet!")),
i18n("Please paste a valid GoogleSheet link in the dialog box above."),
dismissible = TRUE
)
),
uiOutput(
outputId = ns("container_confirm_btn"),
style = "margin-top: 20px;"
)
)
}
#' @inheritParams import_globalenv_server
#'
#' @export
#'
#' @importFrom shiny moduleServer
#' @importFrom shiny reactiveValues observeEvent removeUI reactive req
#' @importFrom htmltools tags tagList
#'
#' @rdname import-googlesheets
import_googlesheets_server <- function(id,
btn_show_data = TRUE,
show_data_in = c("popup", "modal"),
trigger_return = c("button", "change"),
return_class = c("data.frame", "data.table", "tbl_df", "raw"),
reset = reactive(NULL)) {
trigger_return <- match.arg(trigger_return)
return_class <- match.arg(return_class)
module <- function(input, output, session) {
ns <- session$ns
imported_rv <- reactiveValues(data = NULL, name = NULL)
temporary_rv <- reactiveValues(data = NULL, name = NULL, status = NULL)
observeEvent(reset(), {
temporary_rv$data <- NULL
temporary_rv$name <- NULL
temporary_rv$status <- NULL
})
output$container_confirm_btn <- renderUI({
if (identical(trigger_return, "button")) {
button_import()
}
})
observeEvent(input$trigger, {
if (identical(trigger_return, "change")) {
hideUI(selector = paste0("#", ns("confirm-button")))
}
})
observeEvent(input$link, {
req(input$link)
imported <- try(read_gsheet(input$link), silent = TRUE)
if (inherits(imported, "try-error") || NROW(imported) < 1) {
toggle_widget(inputId = "confirm", enable = FALSE)
insert_error(mssg = i18n(attr(imported, "condition")$message))
temporary_rv$status <- "error"
temporary_rv$data <- NULL
} else {
toggle_widget(inputId = "confirm", enable = TRUE)
insert_alert(
selector = ns("import"),
status = "success",
make_success_alert(
imported,
trigger_return = trigger_return,
btn_show_data = btn_show_data
)
)
temporary_rv$status <- "success"
temporary_rv$data <- imported
}
}, ignoreInit = TRUE)
observeEvent(input$see_data, {
show_data(temporary_rv$data, title = i18n("Imported data"), type = show_data_in)
})
observeEvent(input$confirm, {
imported_rv$data <- temporary_rv$data
})
if (identical(trigger_return, "button")) {
return(list(
status = reactive(temporary_rv$status),
name = reactive(imported_rv$name),
data = reactive(as_out(imported_rv$data, return_class))
))
} else {
return(list(
status = reactive(temporary_rv$status),
name = reactive(temporary_rv$name),
data = reactive(as_out(temporary_rv$data, return_class))
))
}
}
moduleServer(
id = id,
module = module
)
}
# Utils -------------------------------------------------------------------
get_id <- function(x) {
if (grepl("/d/", x)) {
x <- strsplit(x = x, split = "/")
x <- unlist(x)
x[which(x == "d") + 1]
} else if (grepl("id=", x)) {
x <- regmatches(x, gregexpr("id=[[:alnum:]_-]+", x))
gsub("^id=", "", x[[1]])
} else {
stop("Failed to retrieve Googlesheet ID")
}
}
#' @importFrom data.table fread .SD
#' @importFrom utils type.convert
read_gsheet <- function(url, dec = NULL) {
url_ <- sprintf(
"https://docs.google.com/spreadsheets/export?id=%s&format=csv",
get_id(url)
)
if (grepl("gid=", url)) {
gid <- regmatches(url, gregexpr("gid=[0-9]+", url))
url_ <- paste0(url_, "&", gid[[1]])
}
dt <- fread(input = url_)
if (!is.null(dec)) {
dt <- dt[, lapply(.SD, type.convert, dec = dec)]
}
return(dt)
}
================================================
FILE: R/import-modal.R
================================================
#' @title Import from all sources
#'
#' @description Wrap all import modules into one, can be displayed inline or in a modal window..
#'
#' @param id Module's id
#' @param from The import_ui & server to use, i.e. the method.
#' There are 5 options to choose from. ("env", "file", "copypaste", "googlesheets", "url")
#' @inheritParams import-file
#'
#' @template module-import
#'
#' @export
#' @name import-modal
#'
#' @importFrom shiny NS tabsetPanel tabPanel tabPanelBody icon fluidRow column
#' @importFrom htmltools tags HTML
#' @importFrom shinyWidgets radioGroupButtons
#'
#' @example examples/modal.R
#'
import_ui <- function(id,
from = c("env", "file", "copypaste", "googlesheets", "url"),
file_extensions = c(".csv", ".txt", ".xls", ".xlsx", ".rds", ".fst", ".sas7bdat", ".sav")) {
ns <- NS(id)
from <- match.arg(from, several.ok = TRUE)
env <- if ("env" %in% from) {
tabPanelBody(
value = "env",
tags$br(),
import_globalenv_ui(id = ns("env"), title = NULL)
)
}
file <- if ("file" %in% from) {
tabPanelBody(
value = "file",
tags$br(),
import_file_ui(id = ns("file"), title = NULL, file_extensions = file_extensions)
)
}
copypaste <- if ("copypaste" %in% from) {
tabPanelBody(
value = "copypaste",
tags$br(),
import_copypaste_ui(id = ns("copypaste"), title = NULL)
)
}
googlesheets <- if ("googlesheets" %in% from) {
tabPanelBody(
value = "googlesheets",
tags$br(),
import_googlesheets_ui(id = ns("googlesheets"), title = NULL)
)
}
url <- if ("url" %in% from) {
tabPanelBody(
value = "url",
tags$br(),
import_url_ui(id = ns("url"), title = NULL)
)
}
#database <- if("database" %in% from) tabPanel("Database", import_database_ui(ns("database")))
labsImport <- list(
"env" = i18n("Environment"),
"file" = i18n("External file"),
"copypaste" = i18n("Copy / Paste"),
"googlesheets" = i18n("Googlesheets"),
"url" = i18n("URL")
)
iconsImport <- list(
"env" = phosphoricons::ph("code", title = labsImport$env),
"file" = phosphoricons::ph("file-arrow-down", title = labsImport$file),
"copypaste" = phosphoricons::ph("clipboard-text", title = labsImport$copypaste),
"googlesheets" = phosphoricons::ph("cloud-arrow-down", title = labsImport$googlesheets),
"url" = phosphoricons::ph("link", title = labsImport$url)
)
if (identical(length(from), 1L)) {
importTab <- switch(
from,
"env" = import_globalenv_ui(id = ns("env")),
"file" = import_file_ui(id = ns("file"), file_extensions = file_extensions),
"copypaste" = import_copypaste_ui(id = ns("copypaste")),
"googlesheets" = import_googlesheets_ui(id = ns("googlesheets")),
"url" = import_url_ui(id = ns("url")),
)
} else {
tabsetPanelArgs <- dropNulls(list(
env, file, copypaste, googlesheets, url,
id = ns("tabs-import"),
type = "hidden"
))
importTab <- do.call(
what = tabsetPanel,
args = tabsetPanelArgs
)
importTab <- fluidRow(
column(
width = 3,
tags$br(),
tags$style(
HTML(sprintf("#%s>.btn-group-vertical {width: 100%%;}", ns("from"))),
HTML(sprintf(".btn-group-vertical>.btn-group>.btn {text-align: left;}"))
),
radioGroupButtons(
inputId = ns("from"),
label = i18n("How to import data?"),
choiceValues = from,
choiceNames = lapply(
X = from,
FUN = function(x) {
tagList(iconsImport[[x]], labsImport[[x]])
}
),
direction = "vertical",
width = "100%"
)
),
column(
width = 9, importTab
)
)
}
tags$div(
class = "datamods-imports",
html_dependency_datamods(),
tags$style(".tui-grid-cell-summary {vertical-align: baseline;}"),
bslib::navset_underline(
id = ns("tabs-mode"),
bslib::nav_panel(
title = tagList(
phosphoricons::ph("download-simple", title = i18n("Import")),
i18n("Import")
),
value = "import",
importTab
),
bslib::nav_panel(
title = tagList(
phosphoricons::ph("table", title = i18n("View")),
i18n("View")
),
value = "view",
tags$br(),
tags$div(
style = css(minHeight = "600px"),
toastui::datagridOutput(outputId = ns("view"), height = "auto")
)
),
bslib::nav_panel(
title = tagList(
phosphoricons::ph("gear-six", title = i18n("Update")),
i18n("Update")
),
value = "update",
tags$br(),
update_variables_ui(id = ns("update"), title = NULL)
),
bslib::nav_panel(
title = tagList(
phosphoricons::ph("shield-check", title = i18n("Validate")),
i18n("Validate")
),
value = "validate",
tags$br(),
validation_ui(
id = ns("validation"),
display = "inline",
max_height = "400px"
)
)
),
tags$div(
id = ns("confirm-button"),
style = "margin-top: 20px;",
button_import(list(ns = ns))
),
tags$div(
style = "display: none;",
textInput(inputId = ns("hidden"), label = NULL, value = genId())
),
tags$script(
sprintf("$('#%s').addClass('nav-justified');", ns("tabs-mode")),
sprintf("fadeTab({id: '%s'});", ns("tabs-mode")),
sprintf("disableTab({id: '%s', value: '%s'});", ns("tabs-mode"), "view"),
sprintf("disableTab({id: '%s', value: '%s'});", ns("tabs-mode"), "update"),
sprintf("disableTab({id: '%s', value: '%s'});", ns("tabs-mode"), "validate")
)
)
}
#' @param validation_opts `list` of arguments passed to [validation_server().
#' @param allowed_status Vector of statuses allowed to confirm dataset imported,
#' if you want that all validation rules are successful before importing data use `allowed_status = "OK"`.
#' @param return_class Class of returned data: `data.frame`, `data.table`, `tbl_df` (tibble) or `raw`.
#'
#' @export
#' @rdname import-modal
#' @importFrom shiny moduleServer reactiveValues observeEvent
#' reactive removeModal updateTabsetPanel hideTab observe
#' @importFrom rlang %||%
import_server <- function(id,
validation_opts = NULL,
allowed_status = c("OK", "Failed", "Error"),
return_class = c("data.frame", "data.table", "tbl_df", "raw"),
read_fns = list()) {
allowed_status <- match.arg(allowed_status, several.ok = TRUE)
return_class <- match.arg(return_class)
if (length(read_fns) > 0) {
if (!is_named(read_fns))
stop("import_file_server: `read_fns` must be a named list.", call. = FALSE)
if (!all(vapply(read_fns, is_function, logical(1))))
stop("import_file_server: `read_fns` must be list of function(s).", call. = FALSE)
}
moduleServer(
id,
function(input, output, session) {
ns <- session$ns
data_rv <- reactiveValues(data = NULL)
imported_rv <- reactiveValues(data = NULL)
observeEvent(input$hidden, {
data_rv$data <- NULL
data_rv$name <- NULL
if (length(validation_opts) < 1) {
hideTab(inputId = "tabs-mode", target = "validate")
}
})
observeEvent(input$from, {
updateTabsetPanel(
session = session,
inputId = "tabs-import",
selected = input$from
)
})
from_env <- import_globalenv_server(
id = "env",
trigger_return = "change",
btn_show_data = FALSE,
reset = reactive(input$hidden)
)
from_file <- import_file_server(
id = "file",
trigger_return = "change",
btn_show_data = FALSE,
reset = reactive(input$hidden),
read_fns = read_fns
)
from_copypaste <- import_copypaste_server(
id = "copypaste",
trigger_return = "change",
btn_show_data = FALSE,
reset = reactive(input$hidden)
)
from_googlesheets <- import_googlesheets_server(
id = "googlesheets",
trigger_return = "change",
btn_show_data = FALSE,
reset = reactive(input$hidden)
)
from_url <- import_url_server(
id = "url",
trigger_return = "change",
btn_show_data = FALSE,
reset = reactive(input$hidden)
)
#from_database <- import_database_server("database")
observeEvent(from_env$data(), {
data_rv$data <- from_env$data()
data_rv$name <- from_env$name()
})
observeEvent(from_file$data(), {
data_rv$data <- from_file$data()
data_rv$name <- from_file$name()
})
observeEvent(from_copypaste$data(), {
data_rv$data <- from_copypaste$data()
data_rv$name <- from_copypaste$name()
})
observeEvent(from_googlesheets$data(), {
data_rv$data <- from_googlesheets$data()
data_rv$name <- from_googlesheets$name()
})
observeEvent(from_url$data(), {
data_rv$data <- from_url$data()
data_rv$name <- from_url$name()
})
# observeEvent(from_database$data(), {
# data_rv$data <- from_database$data()
# })
observeEvent(data_rv$data, {
req(data_rv$data)
if (is.data.frame(data_rv$data)) {
if (length(validation_opts) < 1) {
toggle_widget(inputId = "confirm", enable = TRUE)
} else {
status <- validation_results$status()
if (isTRUE(status %in% allowed_status)) {
toggle_widget(inputId = "confirm", enable = TRUE)
} else {
toggle_widget(inputId = "confirm", enable = FALSE)
}
}
enable_tab("tabs-mode", "view")
enable_tab("tabs-mode", "update")
enable_tab("tabs-mode", "validate")
} else {
toggle_widget(inputId = "confirm", enable = FALSE)
}
})
output$view <- toastui::renderDatagrid({
data <- req(data_rv$data)
session <- shiny::getDefaultReactiveDomain()
gridTheme <- getOption("datagrid.theme")
if (length(gridTheme) < 1) {
apply_grid_theme()
}
on.exit(toastui::reset_grid_theme())
grid <- toastui::datagrid(
data = data,
summary = construct_col_summary(data),
colwidths = "guess",
minBodyHeight = 500
)
toastui::grid_columns(grid, className = "font-monospace")
})
updated_data <- update_variables_server(
id = "update",
data = reactive(data_rv$data),
height = "300px"
)
validation_results <- validation_server(
id = "validation",
data = reactive({
data_rv$data
}),
n_row = validation_opts$n_row,
n_col = validation_opts$n_col,
n_row_label = validation_opts$n_row_label %||% "Valid number of rows",
n_col_label = validation_opts$n_col_label %||% "Valid number of columns",
btn_label = validation_opts$btn_label,
rules = validation_opts$rules
)
observeEvent(validation_results$status(), {
status <- validation_results$status()
req(status)
if (status %in% c("Error", "Failed")) {
update_tab_label("tabs-mode", "validate", tagList(
phosphoricons::ph("warning-circle", weight = "fill", fill = "firebrick"), i18n("Validate")
))
} else {
update_tab_label("tabs-mode", "validate", i18n("Validate"))
}
if (status %in% allowed_status) {
toggle_widget(inputId = "confirm", enable = TRUE)
} else {
toggle_widget(inputId = "confirm", enable = FALSE)
}
})
observeEvent(updated_data(), {
data_rv$data <- updated_data()
})
observeEvent(input$confirm, {
removeModal()
imported_rv$data <- data_rv$data
imported_rv$name <- data_rv$name %||% "imported_data"
})
return(list(
data = reactive(as_out(imported_rv$data, return_class)),
name = reactive(imported_rv$name)
))
}
)
}
#' @param title Modal window title.
#' @param size Modal window size, default to \code{"l"} (large).
#'
#' @export
#' @rdname import-modal
#' @importFrom shiny modalDialog showModal
#' @importFrom htmltools tags css
import_modal <- function(id,
from,
title = i18n("Import data"),
size = "l",
file_extensions = c(".csv", ".txt", ".xls", ".xlsx", ".rds", ".fst", ".sas7bdat", ".sav")) {
showModal(modalDialog(
title = tagList(
button_close_modal(),
title
),
import_ui(id, from, file_extensions = file_extensions),
size = size,
footer = NULL
))
}
================================================
FILE: R/import-url.R
================================================
#' @title Import data from a URL
#'
#' @description Let user paste link to a JSON then import the data.
#'
#' @inheritParams import-globalenv
#'
#' @template module-import
#'
#' @export
#' @name import-url
#'
#' @importFrom htmltools tags
#'
#' @example examples/from-url.R
import_url_ui <- function(id, title = TRUE) {
ns <- shiny::NS(id)
if (isTRUE(title)) {
title <- tags$h4(
i18n("Import Url"),
class = "datamods-title"
)
}
tags$div(
class = "datamods-import",
html_dependency_datamods(),
title,
shinyWidgets::textInputIcon(
inputId = ns("link"),
label = i18n("Enter URL to data:"),
icon = phosphoricons::ph("link"),
width = "100%"
),
tags$div(
id = ns("import-placeholder"),
alert(
id = ns("import-result"),
status = "info",
tags$b(i18n("Nothing pasted yet!")),
i18n("Please paste a valid link in the dialog box above."),
i18n("You can import from flat table format supported by"),
tags$a(
href = "https://CRAN.R-project.org/package=rio/vignettes/rio.html#Supported_file_formats",
"package rio"
),
dismissible = TRUE
)
),
shiny::uiOutput(
outputId = ns("container_confirm_btn"),
style = "margin-top: 20px;"
)
)
}
#' @inheritParams import_globalenv_server
#'
#' @export
#'
#' @importFrom shiny moduleServer
#' @importFrom shiny reactiveValues observeEvent removeUI reactive req
#' @importFrom htmltools tags tagList
#'
#' @rdname import-url
import_url_server <- function(id,
btn_show_data = TRUE,
show_data_in = c("popup", "modal"),
trigger_return = c("button", "change"),
return_class = c("data.frame", "data.table", "tbl_df", "raw"),
reset = reactive(NULL)) {
trigger_return <- match.arg(trigger_return)
return_class <- match.arg(return_class)
module <- function(input, output, session) {
ns <- session$ns
imported_rv <- reactiveValues(data = NULL, name = NULL)
temporary_rv <- reactiveValues(data = NULL, name = NULL, status = NULL)
observeEvent(reset(), {
temporary_rv$data <- NULL
temporary_rv$name <- NULL
temporary_rv$status <- NULL
})
output$container_confirm_btn <- renderUI({
if (identical(trigger_return, "button")) {
button_import()
}
})
observeEvent(input$trigger, {
if (identical(trigger_return, "change")) {
hideUI(selector = paste0("#", ns("confirm-button")))
}
})
observeEvent(input$link, {
req(input$link)
imported <- try(rio::import(input$link), silent = TRUE)
if (inherits(imported, "try-error")) # retry with explicit json format
imported <- try(rio::import(input$link, format = "json"), silent = TRUE)
if (inherits(imported, "try-error") || NROW(imported) < 1) {
toggle_widget(inputId = "confirm", enable = FALSE)
# pass error message to UI
insert_error(mssg = i18n(attr(imported, "condition")$message))
temporary_rv$status <- "error"
temporary_rv$data <- NULL
temporary_rv$name <- NULL
} else {
toggle_widget(inputId = "confirm", enable = TRUE)
insert_alert(
selector = ns("import"),
status = "success",
make_success_alert(
imported,
trigger_return = trigger_return,
btn_show_data = btn_show_data
)
)
temporary_rv$status <- "success"
temporary_rv$data <- imported
temporary_rv$name <- basename(input$link)
}
}, ignoreInit = TRUE)
observeEvent(input$see_data, {
show_data(temporary_rv$data, title = i18n("Imported data"), type = show_data_in)
})
observeEvent(input$confirm, {
imported_rv$data <- temporary_rv$data
imported_rv$name <- temporary_rv$name
})
if (identical(trigger_return, "button")) {
return(list(
status = reactive(temporary_rv$status),
name = reactive(imported_rv$name),
data = reactive(as_out(imported_rv$data, return_class))
))
} else {
return(list(
status = reactive(temporary_rv$status),
name = reactive(temporary_rv$name),
data = reactive(as_out(temporary_rv$data, return_class))
))
}
}
moduleServer(
id = id,
module = module
)
}
================================================
FILE: R/onLoad.R
================================================
#' Shiny resource
#'
#' @importFrom shiny addResourcePath
#'
#' @noRd
.onLoad <- function(...) {
shiny::addResourcePath("datamods", system.file("assets", package = "datamods"))
}
================================================
FILE: R/sample-data.R
================================================
## Function sample_n()
#' @title Sample rows
#'
#' @description The `sample_n` function returns the sample of a dataset from a number of rows chosen by the user.
#'
#' @param data `data.frame`
#' @param n vector of type `numeric`
#'
#' @return the sample of a dataset in the form of `data.table`
#'
#' @noRd
#'
#' @importFrom data.table as.data.table .N
#'
#' @examples
#' sample_n(iris, 25)
sample_n <- function(data, n) {
as.data.table(data)[sample(x = .N, size = n)]
}
## Function sample_prop()
#' @title Sample percentage
#'
#' @description The `sample_prop` function returns the sample of a dataset from a percentage chosen by the user.
#'
#' @param data `data.frame`
#' @param percentage vector of type `numeric`
#'
#' @return the sample of a dataset in the form of `data.table`
#'
#' @noRd
#'
#' @importFrom data.table as.data.table .N
#'
sample_prop <- function(data, prop) {
as.data.table(data)[sample(x = .N, size = nrow(data) * (prop/100))]
}
## Function sample_ui()
#' @title Shiny module to interactively sample a `data.frame`
#'
#' @description Allow to take a sample of `data.frame` for a given number or proportion of rows to keep.
#'
#' @param id Module id. See [shiny::moduleServer()].
#'
#' @return
#' * UI: HTML tags that can be included in shiny's UI
#' * Server: a `reactive` fgunction with the sampled data.
#'
#' @export
#'
#' @name module-sample
#'
#' @importFrom htmltools tagList
#' @importFrom shinyWidgets radioGroupButtons
#' @importFrom shiny NS conditionalPanel sliderInput uiOutput
#'
#' @example examples/sample.R
sample_ui <- function(id) {
ns <- NS(id)
tagList(
radioGroupButtons(
inputId = ns("choice"),
label = i18n("Sample data by :"),
choiceNames = c(i18n("number of rows"), i18n("proportion of rows")),
choiceValues = c("number of rows", "proportion of rows"),
justified = TRUE,
size = "xs",
width = "100%"
),
conditionalPanel(
condition = "input.choice == `proportion of rows`",
ns = ns,
sliderInput(
inputId = ns("proportion_rows"),
label = i18n("Choose a percentage :"),
min = 0,
max = 100,
value = 100,
post = " %",
width = "100%"
),
uiOutput(outputId = ns("feedback_proportion_rows"))
),
conditionalPanel(
condition = "input.choice == `number of rows`",
ns = ns,
sliderInput(
inputId = ns("number_rows"),
label = i18n("Choose a number of rows :"),
min = 0,
max = 10,
value = 10,
width = "100%"
),
uiOutput(outputId = ns("feedback_number_rows"))
)
)
}
## Function sample_server()
#' @param data_r `reactive` containing a `data.frame` to use in the module.
#'
#' @export
#'
#' @rdname module-sample
#'
#' @importFrom shiny moduleServer observeEvent updateSliderInput renderUI reactive
#' @importFrom htmltools tags div
#'
sample_server <- function(id, data_r = reactive(NULL)) {
moduleServer(
id,
function(input, output, session) {
observeEvent(data_r(), {
req(data_r())
updateSliderInput(
session,
inputId = "number_rows",
min = 0,
max = nrow(data_r()),
value = nrow(data_r())
)
})
output$feedback_proportion_rows <- renderUI({
sample <- req(sample_r())
tags$div(
paste(input$proportion_rows, i18n("% of the total, i.e."), nrow(sample), i18n("rows"))
)
})
output$feedback_number_rows <- renderUI({
data <- req(data_r())
tags$div(
paste(input$number_rows, i18n("lines, i.e."), round(input$number_rows / nrow(data) * 100, 1), i18n("% of the total"))
)
})
sample_r <- reactive({
req(data_r())
if (input$choice == "proportion of rows") {
table_sample <- sample_prop(data = data_r(), prop = input$proportion_rows)
} else {
table_sample <- sample_n(data = data_r(), n = input$number_rows)
}
return(table_sample)
})
return(sample_r)
}
)
}
================================================
FILE: R/select-group.R
================================================
#' @title Select Group Input Module
#'
#' @description Group of mutually dependent select menus for filtering `data.frame`'s columns (like in Excel).
#'
#' @param id Module's id.
#' @param params A list of parameters passed to each [shinyWidgets::virtualSelectInput()],
#' you can use :
#' * `inputId`: mandatory, must correspond to variable name.
#' * `label`: Display label for the control.
#' * `placeholder`: Text to show when no options selected.
#' @param label Character, global label on top of all labels.
#' @param btn_reset_label Character, reset button label. If `NULL` no button is added.
#' @param inline If `TRUE` (the default),
#' select menus are horizontally positioned, otherwise vertically.
#' @param vs_args Arguments passed to all [shinyWidgets::virtualSelectInput()] created.
#'
#' @return A [shiny::reactive()] function containing data filtered with an attribute `inputs` containing a named list of selected inputs.
#' @export
#'
#' @name select-group
#'
#' @importFrom utils modifyList
#' @importFrom htmltools tagList tags css
#' @importFrom shiny NS actionLink icon singleton
#' @importFrom shinyWidgets virtualSelectInput
#'
#' @example examples/select-group-default.R
#' @example examples/select-group-selected.R
select_group_ui <- function(
id,
params,
label = NULL,
btn_reset_label = "Reset filters",
inline = TRUE,
vs_args = list()
) {
ns <- NS(id)
button_reset <- if (!is.null(btn_reset_label)) {
actionLink(
inputId = ns("reset_all"),
label = tagList(
phosphoricons::ph("x", title = btn_reset_label),
btn_reset_label
),
icon = NULL,
style = "text-align: right;"
)
}
label_tag <- if (!is.null(label)) tags$b(label, class = "select-group-label")
sel_tag <- lapply(
X = seq_along(params),
FUN = function(x) {
input <- params[[x]]
vs_args <- modifyList(
x = vs_args,
val = list(
inputId = ns(input$inputId),
label = input$label,
placeholder = input$placeholder,
choices = input$selected,
selected = input$selected,
multiple = ifelse(is.null(input$multiple), TRUE, input$multiple),
width = "100%"
),
keep.null = TRUE
)
if (is.null(vs_args$showValueAsTags)) vs_args$showValueAsTags <- TRUE
if (is.null(vs_args$zIndex)) vs_args$zIndex <- 10
if (is.null(vs_args$disableSelectAll)) vs_args$disableSelectAll <- TRUE
tags$div(
class = "select-group-item",
id = ns(paste0("container-", input$inputId)),
do.call(shinyWidgets::virtualSelectInput, vs_args)
)
}
)
if (isTRUE(inline)) {
sel_tag <- tags$div(
class = "select-group-container",
style = htmltools::css(
display = "grid",
gridTemplateColumns = sprintf("repeat(%s, 1fr)", length(params)),
gridColumnGap = "5px"
),
sel_tag
)
}
tags$div(
class = "select-group",
label_tag,
sel_tag,
button_reset,
html_dependency_datamods()
)
}
#' @param data_r Either a [data.frame()] or a [shiny::reactive()]
#' function returning a `data.frame` (do not use parentheses).
#' @param vars_r character, columns to use to create filters,
#' must correspond to variables listed in `params`. Can be a
#' [shiny::reactive()] function, but values must be included in the initial ones (in `params`).
#' @param selected_r [shiny::reactive()] function returning a named list with selected values to set.
#'
#' @export
#'
#' @rdname select-group
#' @importFrom shiny observeEvent observe reactiveValues reactive is.reactive isolate isTruthy
#' @importFrom shinyWidgets updateVirtualSelect
#' @importFrom rlang %||%
select_group_server <- function(id, data_r, vars_r, selected_r = reactive(list())) {
moduleServer(
id = id,
module = function(input, output, session) {
# Namespace
ns <- session$ns
hideUI(selector = paste0("#", ns("reset_all")))
# data <- as.data.frame(data)
rv <- reactiveValues(data = NULL, vars = NULL)
observe({
if (is.reactive(data_r)) {
rv$data <- data_r()
} else {
rv$data <- as.data.frame(data_r)
}
if (is.reactive(vars_r)) {
rv$vars <- vars_r()
} else {
rv$vars <- vars_r
}
for (var in names(rv$data)) {
if (var %in% rv$vars) {
showUI(id = paste0("container-", var))
} else {
hideUI(id = paste0("container-", var))
}
}
})
observe({
selected <- selected_r()
if (!is.list(selected)) selected <- list()
lapply(
X = rv$vars,
FUN = function(x) {
vals <- sort(unique(rv$data[[x]]))
shinyWidgets::updateVirtualSelect(
session = session,
inputId = x,
choices = vals,
selected = selected[[x]] %||% isolate(input[[x]])
)
}
)
})
observeEvent(input$reset_all, {
lapply(
X = rv$vars,
FUN = function(x) {
vals <- sort(unique(rv$data[[x]]))
shinyWidgets::updateVirtualSelect(
session = session,
inputId = x,
choices = vals
)
}
)
})
observe({
vars <- rv$vars
lapply(
X = vars,
FUN = function(x) {
ovars <- vars[vars != x]
observeEvent(
input[[x]],
{
data <- rv$data
indicator <- lapply(
X = vars,
FUN = function(x) {
data[[x]] %inT% input[[x]]
}
)
indicator <- Reduce(f = `&`, x = indicator)
data <- data[indicator, ]
if (all(indicator)) {
hideUI(selector = paste0("#", ns("reset_all")))
} else {
showUI(selector = paste0("#", ns("reset_all")))
}
for (i in ovars) {
if (!isTruthy(input[[i]])) {
shinyWidgets::updateVirtualSelect(
session = session,
inputId = i,
choices = sort(unique(data[[i]]))
)
}
}
if (!isTruthy(input[[x]])) {
shinyWidgets::updateVirtualSelect(
session = session,
inputId = x,
choices = sort(unique(data[[x]]))
)
}
},
ignoreNULL = FALSE,
ignoreInit = TRUE
)
}
)
})
return(reactive({
data <- rv$data
vars <- rv$vars
indicator <- lapply(
X = vars,
FUN = function(x) {
data[[x]] %inT% input[[x]]
}
)
indicator <- Reduce(f = `&`, x = indicator)
data <- data[indicator, ]
attr(data, "inputs") <- lapply(
X = setNames(vars, vars),
FUN = function(x) input[[x]]
)
return(data)
}))
}
)
}
================================================
FILE: R/show_data.R
================================================
#' Display a table in a window
#'
#' @param data a data object (either a `matrix` or a `data.frame`).
#' @param title Title to be displayed in window.
#' @param show_classes Show variables classes under variables names in table header.
#' @param type Display table in a pop-up with [shinyWidgets::show_alert()],
#' in modal window with [shiny::showModal()] or in a WinBox window with [shinyWidgets::WinBox()].
#' @param options Arguments passed to [toastui::datagrid()].
#' @param width Width of the window, only used if `type = "popup"` or `type = "winbox"`.
#' @param ... Additional options, such as `wbOptions = wbOptions()` or `wbControls = wbControls()`.
#' @inheritParams shiny::showModal
#'
#' @note
#' If you use `type = "winbox"`, you'll need to use `shinyWidgets::html_dependency_winbox()` somewhere in your UI.
#'
#' @return No value.
#' @export
#'
#' @importFrom shinyWidgets show_alert
#' @importFrom htmltools tags tagList css
#' @importFrom shiny showModal modalDialog
#' @importFrom utils modifyList packageVersion
#'
#' @example examples/show_data.R
show_data <- function(data,
title = NULL,
options = NULL,
show_classes = TRUE,
type = c("popup", "modal", "winbox"),
width = "65%",
...,
session = shiny::getDefaultReactiveDomain()) { # nocov start
type <- match.arg(type)
data <- as.data.frame(data)
args <- list(...)
gridTheme <- getOption("datagrid.theme")
if (length(gridTheme) < 1) {
apply_grid_theme()
}
on.exit(toastui::reset_grid_theme())
if (is.null(options))
options <- list()
options$height <- 550
options$minBodyHeight <- 400
options$data <- data
options$theme <- "default"
options$colwidths <- "guess"
options$guess_colwidths_opts <- list(min_width = 90, max_width = 400, mul = 1, add = 10)
if (isTRUE(show_classes))
options$summary <- construct_col_summary(data)
datatable <- rlang::exec(toastui::datagrid, !!!options)
datatable <- toastui::grid_columns(datatable, className = "font-monospace")
if (is.null(session))
return(datatable)
if (identical(type, "winbox")) {
wb_options <- if (is.null(args$wbOptions)) {
shinyWidgets::wbOptions(
height = "600px",
width = width,
modal = TRUE
)
} else {
modifyList(
shinyWidgets::wbOptions(
height = "600px",
width = width,
modal = TRUE
),
args$wbOptions
)
}
wb_controls <- if (is.null(args$wbControls)) {
shinyWidgets::wbControls()
} else {
args$wbControls
}
shinyWidgets::WinBox(
title = title,
ui = datatable,
options = wb_options,
controls = wb_controls,
padding = "0 5px",
session = session
)
} else if (identical(type, "popup")) {
show_alert(
title = NULL,
text = tags$div(
if (!is.null(title)) {
tagList(
tags$h3(title),
tags$hr()
)
},
style = "color: #000 !important;",
datatable
),
closeOnClickOutside = TRUE,
showCloseButton = TRUE,
btn_labels = NA,
html = TRUE,
width = width,
session = session
)
} else {
showModal(modalDialog(
title = tagList(
button_close_modal(),
title
),
tags$div(
style = css(minHeight = validateCssUnit(options$height)),
toastui::renderDatagrid2(datatable)
),
size = "xl",
footer = NULL,
easyClose = TRUE
), session = session)
}
} # nocov end
================================================
FILE: R/update-factor.R
================================================
#' @title Module to Reorder the Levels of a Factor Variable
#'
#' @description
#' This module contain an interface to reorder the levels of a factor variable.
#'
#'
#' @param id Module ID.
#'
#' @return A [shiny::reactive()] function returning the data.
#' @export
#'
#' @importFrom shiny NS fluidRow tagList column actionButton
#' @importFrom shinyWidgets virtualSelectInput prettyCheckbox
#' @importFrom toastui datagridOutput
#' @importFrom htmltools tags
#'
#' @name update-factor
#'
#' @example examples/update_factor.R
update_factor_ui <- function(id) {
ns <- NS(id)
tagList(
tags$style(
".tui-grid-row-header-draggable span {width: 3px !important; height: 3px !important;}"
),
fluidRow(
column(
width = 6,
virtualSelectInput(
inputId = ns("variable"),
label = i18n("Factor variable to reorder:"),
choices = NULL,
width = "100%",
zIndex = 50
)
),
column(
width = 3,
class = "d-flex align-items-end",
actionButton(
inputId = ns("sort_levels"),
label = tagList(
ph("sort-ascending"),
i18n("Sort by levels")
),
class = "btn-outline-primary mb-3",
width = "100%"
)
),
column(
width = 3,
class = "d-flex align-items-end",
actionButton(
inputId = ns("sort_occurrences"),
label = tagList(
ph("sort-ascending"),
i18n("Sort by count")
),
class = "btn-outline-primary mb-3",
width = "100%"
)
)
),
datagridOutput(ns("grid")),
tags$div(
class = "float-end",
prettyCheckbox(
inputId = ns("new_var"),
label = i18n("Create a new variable (otherwise replaces the one selected)"),
value = FALSE,
status = "primary",
outline = TRUE,
inline = TRUE
),
actionButton(
inputId = ns("create"),
label = tagList(ph("arrow-clockwise"), i18n("Update factor variable")),
class = "btn-outline-primary"
)
),
tags$div(class = "clearfix")
)
}
#' @param data_r A [shiny::reactive()] function returning a `data.frame`.
#'
#' @export
#'
#' @importFrom shiny moduleServer observeEvent reactive reactiveValues req bindEvent isTruthy updateActionButton
#' @importFrom shinyWidgets updateVirtualSelect
#' @importFrom toastui renderDatagrid datagrid grid_columns grid_colorbar
#'
#' @rdname update-factor
update_factor_server <- function(id, data_r = reactive(NULL)) {
moduleServer(
id,
function(input, output, session) {
rv <- reactiveValues(data = NULL, data_grid = NULL)
bindEvent(observe({
data <- data_r()
rv$data <- data
vars_factor <- vapply(data, is.factor, logical(1))
vars_factor <- names(vars_factor)[vars_factor]
updateVirtualSelect(
inputId = "variable",
choices = vars_factor,
selected = if (isTruthy(input$variable)) input$variable else vars_factor[1]
)
}), data_r(), input$hidden)
observeEvent(input$variable, {
data <- req(data_r())
variable <- req(input$variable)
grid <- as.data.frame(table(data[[variable]]))
rv$data_grid <- grid
})
observeEvent(input$sort_levels, {
if (input$sort_levels %% 2 == 1) {
decreasing <- FALSE
label <- tagList(
ph("sort-descending"),
"Sort Levels"
)
} else {
decreasing <- TRUE
label <- tagList(
ph("sort-ascending"),
"Sort Levels"
)
}
updateActionButton(inputId = "sort_levels", label = as.character(label))
rv$data_grid <- rv$data_grid[order(rv$data_grid[[1]], decreasing = decreasing), ]
})
observeEvent(input$sort_occurrences, {
if (input$sort_occurrences %% 2 == 1) {
decreasing <- FALSE
label <- tagList(
ph("sort-descending"),
i18n("Sort count")
)
} else {
decreasing <- TRUE
label <- tagList(
ph("sort-ascending"),
i18n("Sort count")
)
}
updateActionButton(inputId = "sort_occurrences", label = as.character(label))
rv$data_grid <- rv$data_grid[order(rv$data_grid[[2]], decreasing = decreasing), ]
})
output$grid <- renderDatagrid({
req(rv$data_grid)
gridTheme <- getOption("datagrid.theme")
if (length(gridTheme) < 1) {
apply_grid_theme()
}
on.exit(toastui::reset_grid_theme())
grid <- datagrid(
data = rv$data_grid,
draggable = TRUE,
sortable = FALSE,
data_as_input = TRUE
)
grid <- grid_columns(
grid,
columns = c("Var1", "Freq"),
header = c(i18n("Levels"), i18n("Count"))
)
grid <- grid_colorbar(
grid,
column = "Freq",
label_outside = TRUE,
label_width = "30px",
background = "#D8DEE9",
bar_bg = get_primary_color(),
from = c(0, max(rv$data_grid$Freq) + 1)
)
grid
})
data_updated_r <- reactive({
data <- req(data_r())
variable <- req(input$variable)
grid <- req(input$grid_data)
name_var <- if (isTRUE(input$new_var)) {
paste0(variable, "_updated")
} else {
variable
}
data[[name_var]] <- factor(
as.character(data[[variable]]),
levels = grid[["Var1"]]
)
data
})
data_returned_r <- observeEvent(input$create, {
rv$data <- data_updated_r()
})
return(reactive(rv$data))
}
)
}
#' @inheritParams shiny::modalDialog
#' @export
#'
#' @importFrom shiny showModal modalDialog textInput
#' @importFrom htmltools tagList
#'
#' @rdname update-factor
modal_update_factor <- function(id,
title = i18n("Update levels of a factor"),
easyClose = TRUE,
size = "l",
footer = NULL) {
ns <- NS(id)
showModal(modalDialog(
title = tagList(title, button_close_modal()),
update_factor_ui(id),
tags$div(
style = "display: none;",
textInput(inputId = ns("hidden"), label = NULL, value = genId())
),
easyClose = easyClose,
size = size,
footer = footer
))
}
#' @inheritParams shinyWidgets::WinBox
#' @export
#'
#' @importFrom shinyWidgets WinBox wbOptions wbControls
#' @importFrom htmltools tagList
#' @rdname create-column
winbox_update_factor <- function(id,
title = i18n("Update levels of a factor"),
options = shinyWidgets::wbOptions(),
controls = shinyWidgets::wbControls()) {
ns <- NS(id)
WinBox(
title = title,
ui = tagList(
update_factor_ui(id),
tags$div(
style = "display: none;",
textInput(inputId = ns("hidden"), label = NULL, value = genId())
)
),
options = modifyList(
shinyWidgets::wbOptions(height = "615px", modal = TRUE),
options
),
controls = controls,
auto_height = FALSE
)
}
================================================
FILE: R/update-variables.R
================================================
#' Select, rename and convert variables
#'
#' @param id Module id. See [shiny::moduleServer()].
#' @param title Module's title, if `TRUE` use the default title,
#' use \code{NULL} for no title or a `shiny.tag` for a custom one.
#'
#' @return A [shiny::reactive()] function returning the updated data.
#' @export
#'
#' @name update-variables
#'
#' @importFrom shiny uiOutput actionButton icon
#' @importFrom htmltools tagList tags
#' @importFrom shinyWidgets html_dependency_pretty textInputIcon dropMenu
#'
#' @example examples/variables.R
update_variables_ui <- function(id, title = TRUE) {
ns <- NS(id)
if (isTRUE(title)) {
title <- tags$h4(
i18n("Update & select variables"),
class = "datamods-title"
)
}
tags$div(
class = "datamods-update",
html_dependency_pretty(),
title,
tags$div(
style = "min-height: 25px;",
tags$div(
uiOutput(outputId = ns("data_info"), inline = TRUE),
tagAppendAttributes(
dropMenu(
placement = "bottom-end",
actionButton(
inputId = ns("settings"),
label = phosphoricons::ph("gear"),
class = "pull-right float-right"
),
textInputIcon(
inputId = ns("format"),
label = i18n("Date format:"),
value = "%Y-%m-%d",
icon = list(phosphoricons::ph("clock"))
),
textInputIcon(
inputId = ns("origin"),
label = i18n("Date to use as origin to convert date/datetime:"),
value = "1970-01-01",
icon = list(phosphoricons::ph("calendar"))
),
textInputIcon(
inputId = ns("dec"),
label = i18n("Decimal separator:"),
value = ".",
icon = list("0.00")
)
),
style = "display: inline;"
)
),
tags$br(),
toastui::datagridOutput(outputId = ns("table"))
),
tags$br(),
tags$div(
id = ns("update-placeholder"),
alert(
id = ns("update-result"),
status = "info",
phosphoricons::ph("info"),
i18n(paste(
"Select, rename and convert variables in table above,",
"then apply changes by clicking button below."
))
)
),
actionButton(
inputId = ns("validate"),
label = tagList(
phosphoricons::ph("arrow-circle-right", title = i18n("Apply changes")),
i18n("Apply changes")
),
width = "100%"
)
)
}
#' @export
#'
#' @param id Module's ID
#' @param data a \code{data.frame} or a \code{reactive} function returning a \code{data.frame}.
#' @param height Height for the table.
#' @param return_data_on_init Return initial data when module is called.
#' @param try_silent logical: should the report of error messages be suppressed?
#'
#' @rdname update-variables
#'
#' @importFrom shiny moduleServer reactiveValues reactive renderUI reactiveValuesToList validate need reactiveVal
#' @importFrom rlang call2 expr
#' @importFrom data.table setorderv
update_variables_server <- function(id,
data,
height = NULL,
return_data_on_init = FALSE,
try_silent = FALSE) {
moduleServer(
id = id,
module = function(input, output, session) {
ns <- session$ns
updated_data <- reactiveValues(x = NULL)
data_r <- reactive({
if (is.reactive(data)) {
data()
} else {
data
}
})
output$data_info <- renderUI({
shiny::req(data_r())
data <- data_r()
sprintf(i18n("Data has %s observations and %s variables."), nrow(data), ncol(data))
})
variables_r <- reactive({
shiny::validate(
shiny::need(data(), i18n("No data to display."))
)
data <- data_r()
if (isTRUE(return_data_on_init)) {
updated_data$x <- data
} else {
updated_data$x <- NULL
}
summary_vars(data)
})
output$table <- toastui::renderDatagrid({
req(variables_r())
variables <- variables_r()
update_variables_datagrid(
variables,
height = height,
selectionId = ns("row_selected"),
buttonId = "validate"
)
})
observeEvent(input$validate, {
updated_data$list_rename <- NULL
updated_data$list_select <- NULL
updated_data$list_mutate <- NULL
data <- data_r()
new_selections <- input$row_selected
if (length(new_selections) < 1)
new_selections <- seq_along(data)
data_inputs <- as.data.table(input$table_data)
setorderv(data_inputs, "rowKey")
old_names <- data_inputs$name
new_names <- data_inputs$name_toset
new_names[new_names == "Enter new name"] <- NA
new_names[is.na(new_names)] <- old_names[is.na(new_names)]
new_names[new_names == ""] <- old_names[new_names == ""]
new_classes <- data_inputs$class_toset
new_classes[new_classes == "Select new class"] <- NA
data_sv <- variables_r()
vars_to_change <- get_vars_to_convert(data_sv, setNames(as.list(new_classes), old_names))
res_update <- try({
# convert
if (nrow(vars_to_change) > 0) {
data <- convert_to(
data = data,
variable = vars_to_change$name,
new_class = vars_to_change$class_to_set,
origin = input$origin,
format = input$format,
dec = input$dec
)
}
list_mutate <- attr(data, "code_03_convert")
# rename
list_rename <- setNames(
as.list(old_names),
unlist(new_names, use.names = FALSE)
)
list_rename <- list_rename[names(list_rename) != unlist(list_rename, use.names = FALSE)]
names(data) <- unlist(new_names, use.names = FALSE)
# select
list_select <- setdiff(names(data), names(data)[new_selections])
data <- data[, new_selections, drop = FALSE]
}, silent = try_silent)
if (inherits(res_update, "try-error")) {
insert_error(selector = "update")
} else {
insert_alert(
selector = ns("update"),
status = "success",
tags$b(phosphoricons::ph("check"), i18n("Data successfully updated!"))
)
updated_data$x <- data
updated_data$list_rename <- list_rename
updated_data$list_select <- list_select
updated_data$list_mutate <- list_mutate
}
}, ignoreNULL = TRUE, ignoreInit = TRUE)
return(reactive({
data <- updated_data$x
code <- list()
if (!is.null(data) && isTruthy(updated_data$list_mutate) && length(updated_data$list_mutate) > 0) {
code <- c(code, list(call2("mutate", !!!updated_data$list_mutate)))
}
if (!is.null(data) && isTruthy(updated_data$list_rename) && length(updated_data$list_rename) > 0) {
code <- c(code, list(call2("rename", !!!updated_data$list_rename)))
}
if (!is.null(data) && isTruthy(updated_data$list_select) && length(updated_data$list_select) > 0) {
code <- c(code, list(expr(select(-any_of(c(!!!updated_data$list_select))))))
}
if (length(code) > 0) {
attr(data, "code") <- Reduce(
f = function(x, y) expr(!!x %>% !!y),
x = code
)
}
return(data)
}))
}
)
}
# utils -------------------------------------------------------------------
#' Get variables classes from a \code{data.frame}
#'
#' @param data a \code{data.frame}
#'
#' @return a \code{character} vector as same length as number of variables
#' @noRd
#'
#' @examples
#'
#' get_classes(mtcars)
get_classes <- function(data) {
classes <- lapply(
X = data,
FUN = function(x) {
paste(class(x), collapse = ", ")
}
)
unlist(classes, use.names = FALSE)
}
#' Get count of unique values in variables of \code{data.frame}
#'
#' @param data a \code{data.frame}
#'
#' @return a \code{numeric} vector as same length as number of variables
#' @noRd
#'
#' @importFrom data.table uniqueN
#'
#' @examples
#' get_n_unique(mtcars)
get_n_unique <- function(data) {
u <- lapply(data, FUN = function(x) {
if (is.atomic(x)) {
uniqueN(x)
} else {
NA_integer_
}
})
unlist(u, use.names = FALSE)
}
#' Add padding 0 to a vector
#'
#' @param x a \code{vector}
#'
#' @return a \code{character} vector
#' @noRd
#'
#' @examples
#'
#' pad0(1:10)
#' pad0(c(1, 15, 150, NA))
pad0 <- function(x) {
NAs <- which(is.na(x))
x <- formatC(x, width = max(nchar(as.character(x)), na.rm = TRUE), flag = "0")
x[NAs] <- NA
x
}
#' Variables summary
#'
#' @param data a \code{data.frame}
#'
#' @return a \code{data.frame}
#' @noRd
#'
#' @examples
#'
#' summary_vars(iris)
#' summary_vars(mtcars)
summary_vars <- function(data) {
data <- as.data.frame(data)
datsum <- data.frame(
name = names(data),
class = get_classes(data),
n_missing = unname(colSums(is.na(data))),
stringsAsFactors = FALSE
)
datsum$p_complete <- 1 - datsum$n_missing / nrow(data)
datsum$n_unique <- get_n_unique(data)
datsum
}
add_var_toset <- function(data, var_name, default = "") {
datanames <- names(data)
datanames <- append(
x = datanames,
values = paste0(var_name, "_toset"),
after = which(datanames == var_name)
)
data[[paste0(var_name, "_toset")]] <- default
data[, datanames]
}
#' @importFrom toastui datagrid grid_columns grid_format grid_style_column
#' grid_style_column grid_editor grid_editor_opts grid_selection_row
update_variables_datagrid <- function(data, height = NULL, selectionId = NULL, buttonId = NULL) {
data <- add_var_toset(data, "name", "Enter new name")
data <- add_var_toset(data, "class", "Select new class")
gridTheme <- getOption("datagrid.theme")
if (length(gridTheme) < 1) {
apply_grid_theme()
}
on.exit(toastui::reset_grid_theme())
grid <- datagrid(
data = data,
theme = "default",
colwidths = NULL
)
grid <- grid_columns(
grid = grid,
columns = c("name", "name_toset", "class", "class_toset", "n_missing", "p_complete", "n_unique"),
header = c("Name", "New name", "Class", "New class", "Missing values", "Complete obs.", "Unique values"),
minWidth = 120
)
grid <- grid_format(
grid = grid,
"p_complete",
formatter = toastui::JS("function(obj) {return (obj.value*100).toFixed(0) + '%';}")
)
grid <- grid_style_column(
grid = grid,
column = "name_toset",
fontStyle = "italic"
)
grid <- grid_style_column(
grid = grid,
column = "class_toset",
fontStyle = "italic"
)
grid <- grid_editor(
grid = grid,
column = "name_toset",
type = "text"
)
grid <- grid_editor(
grid = grid,
column = "class_toset",
type = "select",
choices = c("Select new class", "character", "factor", "numeric", "integer", "date", "datetime")
)
grid <- grid_editor_opts(
grid = grid,
editingEvent = "click",
actionButtonId = NULL,
session = NULL
)
grid <- grid_selection_row(
grid = grid,
inputId = selectionId,
type = "checkbox",
return = "index"
)
return(grid)
}
#' Convert a variable to specific new class
#'
#' @param data A \code{data.frame}
#' @param variable Name of the variable to convert
#' @param new_class Class to set
#' @param ... Other arguments passed on to methods.
#'
#' @return A \code{data.frame}
#' @noRd
#'
#' @importFrom utils type.convert
#' @importFrom rlang sym expr
#'
#' @examples
#' dat <- data.frame(
#' v1 = month.name,
#' v2 = month.abb,
#' v3 = 1:12,
#' v4 = as.numeric(Sys.Date() + 0:11),
#' v5 = as.character(Sys.Date() + 0:11),
#' v6 = as.factor(c("a", "a", "b", "a", "b", "a", "a", "b", "a", "b", "b", "a")),
#' v7 = as.character(11:22),
#' stringsAsFactors = FALSE
#' )
#'
#' str(dat)
#'
#' str(convert_to(dat, "v3", "character"))
#' str(convert_to(dat, "v6", "character"))
#' str(convert_to(dat, "v7", "numeric"))
#' str(convert_to(dat, "v4", "date", origin = "1970-01-01"))
#' str(convert_to(dat, "v5", "date"))
#'
#' str(convert_to(dat, c("v1", "v3"), c("factor", "character")))
#'
#' str(convert_to(dat, c("v1", "v3", "v4"), c("factor", "character", "date"), origin = "1970-01-01"))
#'
convert_to <- function(data,
variable,
new_class = c("character", "factor", "numeric", "integer", "date", "datetime"),
...) {
new_class <- match.arg(new_class, several.ok = TRUE)
stopifnot(length(new_class) == length(variable))
args <- list(...)
if (length(variable) > 1) {
for (i in seq_along(variable)) {
data <- convert_to(data, variable[i], new_class[i], ...)
}
return(data)
}
if (identical(new_class, "character")) {
data[[variable]] <- as.character(x = data[[variable]], ...)
attr(data, "code_03_convert") <- c(
attr(data, "code_03_convert"),
setNames(list(expr(as.character(!!sym(variable)))), variable)
)
} else if (identical(new_class, "factor")) {
data[[variable]] <- as.factor(x = data[[variable]])
attr(data, "code_03_convert") <- c(
attr(data, "code_03_convert"),
setNames(list(expr(as.factor(!!sym(variable)))), variable)
)
} else if (identical(new_class, "numeric")) {
data[[variable]] <- as.numeric(type.convert(data[[variable]], as.is = TRUE, ...))
attr(data, "code_03_convert") <- c(
attr(data, "code_03_convert"),
setNames(list(expr(as.numeric(!!sym(variable)))), variable)
)
} else if (identical(new_class, "integer")) {
data[[variable]] <- as.integer(x = data[[variable]], ...)
attr(data, "code_03_convert") <- c(
attr(data, "code_03_convert"),
setNames(list(expr(as.integer(!!sym(variable)))), variable)
)
} else if (identical(new_class, "date")) {
data[[variable]] <- as.Date(x = data[[variable]], ...)
attr(data, "code_03_convert") <- c(
attr(data, "code_03_convert"),
setNames(list(expr(as.Date(!!sym(variable), origin = !!args$origin))), variable)
)
} else if (identical(new_class, "datetime")) {
data[[variable]] <- as.POSIXct(x = data[[variable]], ...)
attr(data, "code_03_convert") <- c(
attr(data, "code_03_convert"),
setNames(list(expr(as.POSIXct(!!sym(variable)))), variable)
)
}
return(data)
}
#' Get variable(s) to convert
#'
#' @param vars Output of [summary_vars()]
#' @param classes_input List of inputs containing new classes
#'
#' @return a `data.table`.
#' @noRd
#'
#' @importFrom data.table data.table as.data.table
#'
#' @examples
#' # 2 variables to convert
#' new_classes <- list(
#' "Sepal.Length" = "numeric",
#' "Sepal.Width" = "numeric",
#' "Petal.Length" = "character",
#' "Petal.Width" = "numeric",
#' "Species" = "character"
#' )
#' get_vars_to_convert(summary_vars(iris), new_classes)
#'
#'
#' # No changes
#' new_classes <- list(
#' "Sepal.Length" = "numeric",
#' "Sepal.Width" = "numeric",
#' "Petal.Length" = "numeric",
#' "Petal.Width" = "numeric",
#' "Species" = "factor"
#' )
#' get_vars_to_convert(summary_vars(iris), new_classes)
#'
#' # Not set = NA or ""
#' new_classes <- list(
#' "Sepal.Length" = NA,
#' "Sepal.Width" = NA,
#' "Petal.Length" = NA,
#' "Petal.Width" = NA,
#' "Species" = NA
#' )
#' get_vars_to_convert(summary_vars(iris), new_classes)
#'
#' # Set for one var
#' new_classes <- list(
#' "Sepal.Length" = "",
#' "Sepal.Width" = "",
#' "Petal.Length" = "",
#' "Petal.Width" = "",
#' "Species" = "character"
#' )
#' get_vars_to_convert(summary_vars(iris), new_classes)
#'
#' new_classes <- list(
#' "mpg" = "character",
#' "cyl" = "numeric",
#' "disp" = "character",
#' "hp" = "numeric",
#' "drat" = "character",
#' "wt" = "character",
#' "qsec" = "numeric",
#' "vs" = "character",
#' "am" = "numeric",
#' "gear" = "character",
#' "carb" = "integer"
#' )
#' get_vars_to_convert(summary_vars(mtcars), new_classes)
get_vars_to_convert <- function(vars, classes_input) {
vars <- as.data.table(vars)
classes_input <- data.table(
name = names(classes_input),
class_to_set = unlist(classes_input, use.names = FALSE),
stringsAsFactors = FALSE
)
classes_input <- classes_input[!is.na(class_to_set) & class_to_set != ""]
classes_df <- merge(x = vars, y = classes_input, by = "name")
classes_df <- classes_df[!is.na(class_to_set)]
classes_df[class != class_to_set]
}
================================================
FILE: R/utils-shiny.R
================================================
#' @importFrom htmltools htmlDependency
#' @importFrom utils packageVersion
html_dependency_datamods <- function() {
htmlDependency(
name = "datamods",
version = packageVersion("datamods"),
src = list(href = "datamods", file = "assets"),
package = "datamods",
script = "js/datamods.js",
stylesheet = "css/datamods.css"
)
}
#' Enable or disable a widget from server
#'
#' @param inputId Widget's inputId.
#' @param enable Enable or disable the input.
#' @param session Shiny session.
#'
#' @noRd
toggle_widget <- function(inputId,
enable = TRUE,
session = shiny::getDefaultReactiveDomain()) {
session$sendCustomMessage(
type = "datamods-toggleWidget",
message = list(id = session$ns(inputId), enable = enable)
)
}
#' Insert an alert into a placeholder in UI
#'
#' @param selector Id for alert, the placeholder maust have \code{"-placeholder"} suffix.
#' @param ... Arguments passed to \code{shinyWidgets::alert}.
#'
#' @return No value.
#' @noRd
#'
#' @importFrom shiny removeUI insertUI
#' @importFrom shinyWidgets alert
#'
insert_alert <- function(selector, ...) {
removeUI(selector = paste0("#", selector, "-result"))
insertUI(
selector = paste0("#", selector, "-placeholder"),
ui = alert(
id = paste0(selector, "-result"),
...
)
)
}
showUI <- function(selector = NULL,
inline = FALSE,
id = NULL,
session = shiny::getDefaultReactiveDomain()) {
if (!is.null(id))
id <- session$ns(id)
session$sendCustomMessage(
type = "datamods-showUI",
message = dropNulls(list(
selector = selector,
inline = inline,
id = id
))
)
}
hideUI <- function(selector = NULL,
inline = FALSE,
id = NULL,
session = shiny::getDefaultReactiveDomain()) {
if (!is.null(id))
id <- session$ns(id)
session$sendCustomMessage(
type = "datamods-hideUI",
message = dropNulls(list(
selector = selector,
inline = inline,
id = id
))
)
}
enable_tab <- function(id, value, session = shiny::getDefaultReactiveDomain()) {
session$sendCustomMessage(
type = "datamods-enableTab",
message = list(id = session$ns(id), value = value)
)
}
disable_tab <- function(id, value, session = shiny::getDefaultReactiveDomain()) {
session$sendCustomMessage(
type = "datamods-disableTab",
message = list(id = session$ns(id), value = value)
)
}
#' @importFrom htmltools doRenderTags
update_tab_label <- function(id, value, label, session = shiny::getDefaultReactiveDomain()) {
session$sendCustomMessage(
type = "datamods-updateTabLabel",
message = list(id = session$ns(id), value = value, label = doRenderTags(label))
)
}
#' @importFrom htmltools tagList tags
#' @importFrom shiny icon getDefaultReactiveDomain
make_success_alert <- function(data,
trigger_return,
btn_show_data,
extra = NULL,
session = shiny::getDefaultReactiveDomain()) {
if (identical(trigger_return, "button")) {
success_message <- tagList(
tags$b(phosphoricons::ph("check", weight = "bold"), i18n("Data ready to be imported!")),
sprintf(
i18n("data has %s obs. of %s variables."),
nrow(data), ncol(data)
),
extra
)
} else {
success_message <- tagList(
tags$b(phosphoricons::ph("check", weight = "bold"), i18n("Data successfully imported!")),
sprintf(
i18n("data has %s obs. of %s variables."),
nrow(data), ncol(data)
),
extra
)
}
if (isTRUE(btn_show_data)) {
success_message <- tagList(
success_message,
tags$br(),
actionLink(
inputId = session$ns("see_data"),
label = tagList(phosphoricons::ph("table"), i18n("click to see data"))
)
)
}
return(success_message)
}
insert_error <- function(mssg = i18n("Something went wrong..."),
selector = "import",
session = shiny::getDefaultReactiveDomain()) {
insert_alert(
selector = session$ns(selector),
status = "danger",
tags$b(phosphoricons::ph("warning"), i18n("Ooops")),
mssg
)
}
#' @importFrom htmltools tagList tags doRenderTags
help_popup <- function(text) {
tagList(
tags$span(
phosphoricons::ph("question", title = i18n("Help")),
`data-toggle` = "popover",
`data-trigger` = "focus",
title = i18n("Help"),
`data-html` = "true",
`data-content` = htmltools::doRenderTags(text),
tabindex = "0",
role = "button"
),
tags$script(
"$(function () { $(\'[data-toggle=\"popover\"]\').popover({container: 'body'}); })"
)
)
}
#' @importFrom shiny actionButton icon getDefaultReactiveDomain
button_import <- function(session = shiny::getDefaultReactiveDomain()) {
actionButton(
inputId = session$ns("confirm"),
label = tagList(
phosphoricons::ph("arrow-circle-right", title = i18n("Import data")),
i18n("Import data")
),
width = "100%",
disabled = "disabled",
class = "btn-primary",
`aria-label` = i18n("Import data")
)
}
button_close_modal <- function() {
tags$button(
phosphoricons::ph("x", title = i18n("Close"), height = "2em"),
class = "btn btn-link",
style = css(border = "0 none", position = "absolute", top = "5px", right = "5px"),
`data-dismiss` = "modal",
`data-bs-dismiss` = "modal",
`aria-label` = i18n("Close")
)
}
#' @importFrom bslib bs_current_theme is_bs_theme bs_get_variables
get_primary_color <- function() {
theme <- bslib::bs_current_theme()
if (!bslib::is_bs_theme(theme)) {
return("#112466")
}
primary <- bslib::bs_get_variables(theme, "primary")
unname(primary)
}
================================================
FILE: R/utils.R
================================================
`%||%` <- function(x, y) {
if (is.null(x))
y
else x
}
dropNulls <- function(x) {
x[!vapply(x, is.null, FUN.VALUE = logical(1))]
}
dropNullsOrEmpty <- function(x) {
x[!vapply(x, nullOrEmpty, FUN.VALUE = logical(1))]
}
nullOrEmpty <- function(x) {
is.null(x) || length(x) == 0 || x == ""
}
#' @importFrom data.table .SD
dropListColumns <- function(x) {
type_col <- vapply(
X = x,
FUN = typeof,
FUN.VALUE = character(1),
USE.NAMES = FALSE
)
if (inherits(x, "data.table")) {
x[, .SD, .SDcols = type_col != "list"]
} else {
x[, type_col != "list", drop = FALSE]
}
}
#' Search for object with specific class in an environment
#'
#' @param what a class to look for
#' @param env An environment
#'
#' @return Character vector of the names of objects, NULL if none
#' @noRd
#'
#' @examples
#'
#' # NULL if no data.frame
#' search_obj("data.frame")
#'
#' library(ggplot2)
#' data("mpg")
#' search_obj("data.frame")
#'
#'
#' gg <- ggplot()
#' search_obj("ggplot")
#'
search_obj <- function(what = "data.frame", env = globalenv()) {
all <- ls(name = env)
objs <- lapply(
X = all,
FUN = function(x) {
if (inherits(get(x, envir = env), what = what)) {
x
} else {
NULL
}
}
)
objs <- unlist(objs)
if (length(objs) == 1 && objs == "") {
NULL
} else {
objs
}
}
#' @importFrom data.table as.data.table
#' @importFrom tibble as_tibble
as_out <- function(x, return_class = c("data.frame", "data.table", "tbl_df", "raw")) {
if (is.null(x))
return(NULL)
return_class <- match.arg(return_class)
if (identical(return_class, "raw"))
return(x)
is_sf <- inherits(x, "sf")
x <- if (identical(return_class, "data.frame")) {
as.data.frame(x)
} else if (identical(return_class, "data.table")) {
as.data.table(x)
} else {
as_tibble(x)
}
if (is_sf)
class(x) <- c("sf", class(x))
return(x)
}
genId <- function(bytes = 12) {
paste(format(as.hexmode(sample(256, bytes, replace = TRUE) - 1), width = 2), collapse = "")
}
makeId <- function(x) {
if (length(x) < 1)
return(NULL)
x <- as.character(x)
x <- lapply(X = x, FUN = function(y) {
paste(as.character(charToRaw(y)), collapse = "")
})
x <- unlist(x, use.names = FALSE)
make.unique(x, sep = "_")
}
`%inT%` <- function(x, table) {
if (!is.null(table) && ! "" %in% table) {
x %in% table
} else {
rep_len(TRUE, length(x))
}
}
`%inF%` <- function(x, table) {
if (!is.null(table) && ! "" %in% table) {
x %in% table
} else {
rep_len(FALSE, length(x))
}
}
#' @importFrom utils hasName
header_with_classes <- function(data) {
function(value) {
if (!hasName(data, value))
return("")
classes <- tags$div(
style = "font-style: italic; font-weight: normal; font-size: small;",
get_classes(data[, value, drop = FALSE])
)
tags$div(title = value, value, classes)
}
}
split_char <- function(x, split = ",") {
if (is.null(x))
return(NULL)
unlist(strsplit(x, split = split))
}
apply_grid_theme <- function() {
toastui::set_grid_theme(
cell.normal.background = "#FFF",
cell.normal.border = "#D8DEE9",
cell.normal.showVerticalBorder = TRUE,
cell.normal.showHorizontalBorder = TRUE,
cell.header.border = "#D8DEE9",
area.header.border = "#4C566A",
cell.summary.border = "#D8DEE9",
cell.summary.showVerticalBorder = TRUE,
cell.summary.showHorizontalBorder = TRUE
)
}
================================================
FILE: R/validation.R
================================================
#' @title Validation module
#'
#' @description Check that a dataset respect some validation expectations.
#'
#' @param id Module's ID.
#' @param display Display validation results in a dropdown menu
#' by clicking on a button or display results directly in interface.
#' @param max_height Maximum height for validation results element, useful if you have many rules.
#' @param ... Arguments passed to \code{actionButton} or \code{uiOutput} depending on display mode,
#' you cannot use \code{inputId}/\code{outputId}, \code{label} or \code{icon} (button only).
#'
#' @return
#' * UI: HTML tags that can be included in shiny's UI
#' * Server: a \code{list} with two slots:
#' + **status**: a \code{reactive} function returning the best status available between \code{"OK"}, \code{"Failed"} or \code{"Error"}.
#' + **details**: a \code{reactive} function returning a \code{list} with validation details.
#' @export
#'
#' @importFrom shiny NS actionButton icon uiOutput
#' @importFrom htmltools tagList validateCssUnit
#' @importFrom shinyWidgets dropMenu
#'
#' @rdname validation
#'
#' @example examples/validation.R
validation_ui <- function(id, display = c("dropdown", "inline"), max_height = NULL, ...) {
ns <- NS(id)
display <- match.arg(display)
max_height <- if (!is.null(max_height)) {
paste0("overflow-y: auto; max-height:", validateCssUnit(max_height), ";")
}
if (identical(display, "dropdown")) {
ui <- dropMenu(
actionButton(
inputId = ns("menu"),
label = tagList(
phosphoricons::ph("caret-down", weight = "fill", title = i18n("Validation:")),
i18n("Validation:")
),
...
),
uiOutput(
outputId = ns("results"),
style = "width: 300px;",
style = max_height
)
)
} else {
ui <- uiOutput(
outputId = ns("results"),
...,
style = max_height
)
}
tagList(
ui, html_dependency_datamods()
)
}
#' @export
#'
#' @param data a \code{reactive} function returning a \code{data.frame}.
#' @param n_row,n_col A one-sided formula to check number of rows and columns respectively, see below for examples.
#' @param n_row_label,n_col_label Text to be displayed with the result of the check for number of rows/columns.
#' @param btn_label Label for the dropdown button, will be followed by validation result.
#' @param rules An object of class \code{validator} created with \code{validate::validator}.
#' @param bs_version Bootstrap version used, it may affect rendering, especially status badges.
#'
#' @rdname validation
#'
#' @importFrom shiny moduleServer reactiveValues observeEvent updateActionButton renderUI reactive
#' @importFrom htmltools doRenderTags tags tagList
validation_server <- function(id,
data,
n_row = NULL,
n_col = NULL,
n_row_label = i18n("Valid number of rows"),
n_col_label = i18n("Valid number of columns"),
btn_label = i18n("Dataset validation:"),
rules = NULL,
bs_version = 3) {
moduleServer(
id = id,
module = function(input, output, session) {
valid_ui <- reactiveValues(x = NULL)
valid_rv <- reactiveValues(status = NULL, details = NULL)
observeEvent(data(), {
to_validate <- data()
valid_dims <- check_data(to_validate, n_row = n_row, n_col = n_col)
if (all(c(valid_dims$nrows, valid_dims$ncols))) {
valid_status <- "OK"
} else {
valid_status <- "Failed"
}
valid_results <- lapply(
X = c("nrows", "ncols"),
FUN = function(x) {
if (is.null(valid_dims[[x]]))
return(NULL)
label <- switch(
x,
"nrows" = n_row_label,
"ncols" = n_col_label
)
list(
status = ifelse(valid_dims[[x]], "OK", "Failed"),
label = paste0("", label, "")
)
}
)
if (!is.null(rules) && inherits(rules, "validator")) {
validate_results <- validate::confront(to_validate, rules)
validate_results <- validate::summary(validate_results)
validate_results <- merge(
x = validate_results,
y = validate::as.data.frame(rules),
by = "name"
)
# validate_results <- format_validate(validate_results)
if (any(validate_results$error)) {
valid_status <- "Error"
} else if (any(validate_results$fails > 0)) {
valid_status <- "Failed"
}
valid_results <- c(
valid_results,
format_validate(validate_results)
)
}
if (identical(valid_status, "OK")) {
label <- doRenderTags(tagList(
btn_label,
tags$span(
class = badge_class(bs_version, "success"),
phosphoricons::ph("check", weight = "bold", title = i18n("OK")),
i18n("OK")
)
))
} else if (identical(valid_status, "Failed")) {
label <- doRenderTags(tagList(
btn_label,
tags$span(
class = badge_class(bs_version, "warning"),
phosphoricons::ph("warning", weight = "bold", title = i18n("Failed")),
i18n("Failed")
)
))
} else if (identical(valid_status, "Error")) {
label <- doRenderTags(tagList(
btn_label,
tags$span(
class = badge_class(bs_version, "danger"),
phosphoricons::ph("x", weight = "bold", title = i18n("Error")),
i18n("Error")
)
))
}
updateActionButton(session = session, inputId = "menu", label = label)
valid_results <- dropNulls(valid_results)
total <- unlist(lapply(valid_results, `[[`, "status"))
header <- tags$div(
class = "datamods-validation-results",
tags$div(
class = "datamods-validation-summary",
style = "border-right: 1px solid #e6e6e6;",
tags$span(
class = badge_class(bs_version, "success"),
i18n("OK"),
tags$span(sum(total == "OK"), class = "datamods-validation-item")
)
),
tags$div(
class = "datamods-validation-summary",
style = "border-right: 1px solid #e6e6e6;",
tags$span(
class = badge_class(bs_version, "warning"),
i18n("Failed"),
tags$span(sum(total == "Failed"), class = "datamods-validation-item")
)
),
tags$div(
class = "datamods-validation-summary",
tags$span(
class = badge_class(bs_version, "danger"),
i18n("Error"),
tags$span(sum(total == "Error"), class = "datamods-validation-item")
)
)
)
valid_ui$x <- tagList(
header,
tags$br(),
make_validation_alerts(valid_results)
)
valid_rv$status <- valid_status
valid_rv$details <- valid_results
})
output$results <- renderUI({
valid_ui$x
})
return(list(
status = reactive(valid_rv$status),
details = reactive(valid_rv$details)
))
}
)
}
#' @importFrom rlang as_label as_function enquo
check_fun <- function(fun, what) {
label <- as_label(enquo(what))
if (inherits(fun, "formula")) {
fun <- as_function(fun)
result <- try(fun(what))
if (inherits(result, "try-error") | !is.logical(result)) {
warning("Checking ", label, " must return a logical", call. = FALSE)
return(FALSE)
}
} else {
result <- NULL
}
return(result)
}
check_data <- function(data, n_row = NULL, n_col = NULL) {
list(
nrows = check_fun(n_row, nrow(data)),
ncols = check_fun(n_col, ncol(data))
)
}
#' @importFrom shiny icon
#' @importFrom shinyWidgets alert
#' @importFrom htmltools HTML
make_validation_alerts <- function(.list) {
lapply(
X = .list,
FUN = function(x) {
icon <- switch(
x$status,
"OK" = phosphoricons::ph("check", title = i18n("OK")),
"Failed" = phosphoricons::ph("warning", title = i18n("Failed")),
"Error" = phosphoricons::ph("x", title = i18n("Error"))
)
status <- switch(
x$status,
"OK" = "success",
"Failed" = "warning",
"Error" = "danger",
"info"
)
alert(
icon, HTML(x$label),
status = status,
style = "margin-bottom: 10px; padding: 10px;"
)
}
)
}
format_validate <- function(data) {
lapply(
X = seq_len(nrow(data)),
FUN = function(i) {
res <- data[i, ]
if (isTRUE(res$error)) {
status <- "Error"
} else {
if (res$fails > 0) {
status <- "Failed"
} else {
status <- "OK"
}
}
if (!is.null(res$label)) {
label <- paste0("", res$label, "")
if (!is.null(res$description) && nzchar(res$description)) {
label <- paste(label, res$description, sep = ": ")
}
} else {
label <- res$name
}
if (identical(status, "Failed")) {
label <- paste0(label, "| failed: ", res$fails, " / ", res$items)
}
list(
status = status,
label = label,
summary = res
)
}
)
}
badge_class <- function(bs_version, status) {
if (!is.numeric(bs_version))
stop("`bs_version` must be a numeric.")
if (bs_version <= 3) {
paste0("label label-", status)
} else {
sprintf("badge badge-%1$s bg-%1$s", status)
}
}
================================================
FILE: R/zzz.R
================================================
utils::globalVariables(c(
"%>%", "filter", "group_by", "label", "translation",
".datamods_edit_update", ".datamods_edit_delete", ".datamods_id",
"..var_edit", "..vars_datamods_edit",
"select", "any_of", "rename",
"class_to_set"
))
================================================
FILE: README.Rmd
================================================
---
output: github_document
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
```
# datamods
> Shiny modules to import and manipulate data into an application or addin.
[](https://CRAN.R-project.org/package=datamods)
[](https://cran.r-project.org/package=datamods)
[](https://github.com/dreamRs/datamods/actions/workflows/R-CMD-check.yaml)
[](https://app.codecov.io/gh/dreamRs/datamods)
### Overview
This package provides custom shiny modules to import data from various sources, select, rename and convert variables in a dataset and validate content with [validate](https://github.com/data-cleaning/validate) package.
The modules can be used in any standard shiny application or RStudio add-in.
### Internationalization
```{r, include=FALSE}
i18n_flag <- function(code, language) {
code <- strsplit(code, split = "|", fixed = TRUE)[[1]]
flag <- sprintf("
", code)
paste(paste(flag, collapse = ""), language)
}
i18n_flags <- function(languages) {
mapply(
FUN = i18n_flag,
code = names(languages),
language = unlist(languages, use.names = FALSE),
USE.NAMES = FALSE
)
}
languages <- list(
gb = "english (default)",
fr = "french",
mk = "macedonian",
"br|pt" = "brazilian portuguese",
al = "albanian",
cn = "chinese",
es = "spanish",
de = "german",
tr = "turkish",
kr = "korean",
pl = "polish",
ja = "japanese"
)
```
Currently you can use {datamods} in the following language: `r i18n_flags(languages)`.
If you want another language to be supported, you can submit a Pull Request to add a CSV file like the one used for french (file is located in `inst/i18n` folder in the package, you can see it [here on GitHub](https://github.com/dreamRs/datamods/blob/master/inst/i18n/fr.csv)).
See the [online vignette](https://dreamrs.github.io/datamods/articles/i18n.html) for more on this topic.
### Installation
Install from [CRAN](https://CRAN.R-project.org/package=datamods) with:
```r
install.packages("datamods")
```
You can install the development version of datamods from [GitHub](https://github.com/dreamRs/datamods) with:
```r
remotes::install_github("dreamRs/datamods")
```
### Import
Import data from:
* **environment**: such as Global environment or from a package
* **file**: text files, Excel, SAS or SPSS format... anything that package [rio](https://github.com/gesistsa/rio#supported-file-formats) can handle
* **copy/paste**: paste data from an other source like Excel or text file
* **Google Sheet**: use the URL to import the Googlesheet
* **URL**: use a URL to import from a flat table
Each module is available in the form `import_file_ui()` / `import_file_server()` and can be use independently.
Or all modules can be launched together in a modal window via `import_modal()` / `import_server()`:

This module also allow to view imported data and to update variables.
### Update
Module `update_variables_ui()` / `update_variables_server()` allow to:
* **select** variables of interest in a dataset
* **rename** variables to be used in application after that
* **convert** variables to change their class, from character to numeric for example

### Validate
Define some validation rules with package [validate](https://github.com/data-cleaning/validate) and check whether data lives up to those expectations.

### Filter
Interactively filter a `data.frame`, this module also generates the code to reproduce the filters.

### Sample
This module extracts a sample from a `data.frame`, based either on a fixed number of rows or on a percentage of total rows.

### Edit
This module makes a `data.frame` editable, allowing the user to add, modify or delete rows.

### Create column
This module allow to enter an expression to create a new column in a `data.frame`.

### Cut numeric variable
This module contain an interface to cut a numeric into several intervals.

### Update factor
This module contain an interface to reorder the levels of a factor variable.

================================================
FILE: README.md
================================================
# datamods
> Shiny modules to import and manipulate data into an application or
> addin.
[](https://CRAN.R-project.org/package=datamods)
[](https://cran.r-project.org/package=datamods)
[](https://github.com/dreamRs/datamods/actions/workflows/R-CMD-check.yaml)
[](https://app.codecov.io/gh/dreamRs/datamods)
### Overview
This package provides custom shiny modules to import data from various
sources, select, rename and convert variables in a dataset and validate
content with [validate](https://github.com/data-cleaning/validate)
package.
The modules can be used in any standard shiny application or RStudio
add-in.
### Internationalization
Currently you can use {datamods} in the following language:
english (default),
french,
macedonian,

brazilian portuguese,
albanian,
chinese,
spanish,
german,
turkish,
korean,
polish,
japanese.
If you want another language to be supported, you can submit a Pull
Request to add a CSV file like the one used for french (file is located
in `inst/i18n` folder in the package, you can see it [here on
GitHub](https://github.com/dreamRs/datamods/blob/master/inst/i18n/fr.csv)).
See the [online
vignette](https://dreamrs.github.io/datamods/articles/i18n.html) for
more on this topic.
### Installation
Install from [CRAN](https://CRAN.R-project.org/package=datamods) with:
``` r
install.packages("datamods")
```
You can install the development version of datamods from
[GitHub](https://github.com/dreamRs/datamods) with:
``` r
remotes::install_github("dreamRs/datamods")
```
### Import
Import data from:
- **environment**: such as Global environment or from a package
- **file**: text files, Excel, SAS or SPSS format… anything that package
[rio](https://github.com/gesistsa/rio#supported-file-formats) can
handle
- **copy/paste**: paste data from an other source like Excel or text
file
- **Google Sheet**: use the URL to import the Googlesheet
- **URL**: use a URL to import from a flat table
Each module is available in the form `import_file_ui()` /
`import_file_server()` and can be use independently.
Or all modules can be launched together in a modal window via
`import_modal()` / `import_server()`:

This module also allow to view imported data and to update variables.
### Update
Module `update_variables_ui()` / `update_variables_server()` allow to:
- **select** variables of interest in a dataset
- **rename** variables to be used in application after that
- **convert** variables to change their class, from character to numeric
for example

### Validate
Define some validation rules with package
[validate](https://github.com/data-cleaning/validate) and check whether
data lives up to those expectations.

### Filter
Interactively filter a `data.frame`, this module also generates the code
to reproduce the filters.

### Sample
This module extracts a sample from a `data.frame`, based either on a
fixed number of rows or on a percentage of total rows.

### Edit
This module makes a `data.frame` editable, allowing the user to add,
modify or delete rows.

### Create column
This module allow to enter an expression to create a new column in a
`data.frame`.

### Cut numeric variable
This module contain an interface to cut a numeric into several
intervals.

### Update factor
This module contain an interface to reorder the levels of a factor
variable.

================================================
FILE: _pkgdown.yml
================================================
url: https://dreamrs.github.io/datamods
template:
bootstrap: 5
bootswatch: zephyr
bslib:
base_font: {google: "Poppins"}
primary: "#112446"
navbar:
bg: primary
authors:
Victor Perrier:
href: https://twitter.com/_pvictorr
html:
Victor Perrier
Fanny Meyer:
href: https://twitter.com/_mfaan
html:
Fanny Meyer
Zauad Shahreer Abeer:
href: https://twitter.com/shahreyarabeer
html:
Zauad Shahreer Abeer
================================================
FILE: cran-comments.md
================================================
## Test environments
* local R installation, R 4.4.1
* ubuntu 22.04, Windows 10, macOS (on GitHub Actions), R 4.4.1
* win-builder (devel)
## R CMD check results
0 errors | 0 warnings | 0 note
Thanks,
Victor
================================================
FILE: data-raw/demo_edit.R
================================================
## code to prepare `demo_edit` dataset goes here
#library(charlatan)
demo_edit <- data.frame(
"name" = ch_name(n = 20),
"job" = ch_job(n = 20),
"credit card provider" = as.factor(ch_credit_card_provider(n = 20)),
"credit card security code" = as.numeric(ch_credit_card_security_code(n = 20)),
"date obtained" = sample(seq(as.Date('2015/01/01'), as.Date('2022/01/01'), by = "year"), 20, replace = TRUE),
"contactless card" = sample(c(TRUE, FALSE), 20, replace = TRUE)
)
demo_edit <- janitor::clean_names(demo_edit)
usethis::use_data(demo_edit, overwrite = TRUE)
================================================
FILE: examples/create_column.R
================================================
library(shiny)
library(datamods)
library(reactable)
ui <- fluidPage(
theme = bslib::bs_theme(version = 5L, preset = "bootstrap"),
shinyWidgets::html_dependency_winbox(),
tags$h2("Create new column"),
fluidRow(
column(
width = 4,
create_column_ui("inline"),
actionButton("modal", "Or click here to open a modal to create a column"),
tags$br(), tags$br(),
actionButton("winbox", "Or click here to open a WinBox to create a column")
),
column(
width = 8,
reactableOutput(outputId = "table"),
verbatimTextOutput("code")
)
)
)
server <- function(input, output, session) {
rv <- reactiveValues(data = MASS::Cars93[, c(1, 3, 4, 5, 6, 10)])
# inline mode
data_inline_r <- create_column_server(
id = "inline",
data_r = reactive(rv$data)
)
observeEvent(data_inline_r(), rv$data <- data_inline_r())
# modal window mode
observeEvent(input$modal, modal_create_column("modal"))
data_modal_r <- create_column_server(
id = "modal",
data_r = reactive(rv$data)
)
observeEvent(data_modal_r(), rv$data <- data_modal_r())
# WinBox window mode
observeEvent(input$winbox, winbox_create_column("winbox"))
data_winbox_r <- create_column_server(
id = "winbox",
data_r = reactive(rv$data)
)
observeEvent(data_winbox_r(), rv$data <- data_winbox_r())
# Show result
output$table <- renderReactable({
data <- req(rv$data)
reactable(
data = data,
bordered = TRUE,
compact = TRUE,
striped = TRUE
)
})
output$code <- renderPrint({
attr(rv$data, "code")
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/cut_variable.R
================================================
library(shiny)
library(datamods)
library(reactable)
ui <- fluidPage(
theme = bslib::bs_theme(version = 5L, preset = "bootstrap"),
shinyWidgets::html_dependency_winbox(),
tags$h2("Convert Numeric to Factor"),
fluidRow(
column(
width = 6,
cut_variable_ui("inline"),
actionButton("modal", "Or click here to open a modal to cut a variable"),
tags$br(), tags$br(),
actionButton("winbox", "Or click here to open a WinBox to cut a variable")
),
column(
width = 6,
reactableOutput(outputId = "table"),
verbatimTextOutput("code")
)
)
)
server <- function(input, output, session) {
rv <- reactiveValues(data = MASS::Cars93[, c(1, 3, 4, 5, 6, 10)])
# inline mode
data_inline_r <- cut_variable_server(
id = "inline",
data_r = reactive(rv$data)
)
observeEvent(data_inline_r(), rv$data <- data_inline_r())
# modal window mode
observeEvent(input$modal, modal_cut_variable("modal"))
data_modal_r <- cut_variable_server(
id = "modal",
data_r = reactive(rv$data)
)
observeEvent(data_modal_r(), rv$data <- data_modal_r())
# WinBox window mode
observeEvent(input$winbox, winbox_cut_variable("winbox"))
data_winbox_r <- cut_variable_server(
id = "winbox",
data_r = reactive(rv$data)
)
observeEvent(data_winbox_r(), rv$data <- data_winbox_r())
# Show result
output$table <- renderReactable({
data <- req(rv$data)
reactable(
data = data,
bordered = TRUE,
compact = TRUE,
striped = TRUE
)
})
output$code <- renderPrint({
attr(rv$data, "code")
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/edit_data-callback.R
================================================
# -------------------------------------------------------------------------
# Edit data only with callbacks -------------------------------------------
# -------------------------------------------------------------------------
# Packages ----------------------------------------------------------------
library(data.table)
library(datamods)
library(shiny)
library(bslib)
library(shinybusy)
library(reactable)
# Fake data ---------------------------------------------------------------
mydata <- charlatan::ch_generate()
setDT(mydata)
mydata[, ID := seq_len(.N)] # internal ID
mydata[, user := paste0("user", seq_len(.N))]
setcolorder(mydata, c("ID", "user"))
path_to_data <- tempfile(pattern = "mydata", fileext = ".rds")
saveRDS(mydata, file = path_to_data)
# Utilities to update data ------------------------------------------------
update_data <- function(modified) {
res <- try({
base <- readRDS(path_to_data)
setDT(base)
base[ID == modified$ID, (names(modified)) := as.list(modified)]
saveRDS(base, path_to_data)
})
inherits(res, "try-error")
}
delete_data <- function(deleted) {
res <- try({
base <- readRDS(path_to_data)
setDT(base)
base <- base[ID != deleted$ID]
saveRDS(base, path_to_data)
})
inherits(res, "try-error")
}
add_data <- function(added) {
res <- try({
base <- readRDS(path_to_data)
setDT(base)
if (added$user %in% base$user) {
shinybusy::report_warning("Warning", "User already exist.")
return(FALSE)
}
added$ID <- max(base$ID) + 1
base <- rbind(base, added[, .SD, .SDcols = !is.na(added)], use.names = TRUE, fill = TRUE)
saveRDS(base, path_to_data)
})
inherits(res, "try-error")
}
# App ---------------------------------------------------------------------
ui <- fluidPage(
theme = bs_theme(
version = 5
),
edit_data_ui(id = "EDIT"),
verbatimTextOutput("result")
)
server <- function(input, output, session) {
data_r <- reactiveFileReader(
intervalMillis = 1000,
session = session,
filePath = path_to_data,
readFunc = readRDS
)
# Tableau
edited_gestion_utilisateurs_r <- edit_data_server(
id = "EDIT",
data_r = data_r,
add = TRUE,
update = TRUE,
delete = TRUE,
download_csv = FALSE,
download_excel = TRUE,
modal_size = "xl",
n_column = 2,
var_edit = c("user", "name", "job", "phone_number"),
callback_update = function(data, row) {
result <- update_data(row)
if (isTRUE(result))
shinybusy::report_failure("Error", "Failed to update data")
removeModal()
return(TRUE)
},
callback_delete = function(data, row) {
result <- delete_data(row)
if (isTRUE(result))
shinybusy::report_failure("Error", "Failed to delete data")
removeModal()
return(TRUE)
},
callback_add = function(data, add) {
result <- add_data(add)
if (isTRUE(result))
shinybusy::report_failure("Error", "Failed to add data")
removeModal()
return(TRUE)
},
only_callback = TRUE,
use_notify = FALSE,
reactable_options = list(
pagination = FALSE,
outline = TRUE,
striped = TRUE,
columns = list(
ID = colDef(show = FALSE)
)
)
)
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/edit_data-callback_add.R
================================================
library(shiny)
library(datamods)
library(bslib)
library(reactable)
ui <- fluidPage(
theme = bs_theme(
version = 5
),
edit_data_ui(id = "id"),
verbatimTextOutput("result")
)
server <- function(input, output, session) {
edited_r <- edit_data_server(
id = "id",
data_r = reactive(data.frame(Month = month.name, Values = 1:12)),
add = TRUE,
callback_add = function(data, add) {
print(data)
print(add)
if (!add$Month %in% month.name)
return(FALSE)
if (add$Values > 20) {
shinybusy::notify_warning("Value must be equal or inferior to 20")
return(FALSE)
}
# else add data to table
return(TRUE)
}
)
output$result <- renderPrint({
str(edited_r())
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/edit_data-callback_delete.R
================================================
library(shiny)
library(datamods)
library(bslib)
library(reactable)
ui <- fluidPage(
theme = bs_theme(
version = 5
),
edit_data_ui(id = "id"),
verbatimTextOutput("result")
)
server <- function(input, output, session) {
edited_r <- edit_data_server(
id = "id",
data_r = reactive(data.frame(Month = month.name, Values = 1:12)),
add = TRUE,
callback_delete = function(data, row) {
print(data)
print(row)
if (row$Month == "September") {
shinybusy::notify_warning("You cannot delete September")
return(FALSE)
}
return(TRUE)
}
)
output$result <- renderPrint({
str(edited_r())
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/edit_data-callback_update-row_style.R
================================================
library(shiny)
# library(datamods)
pkgload::load_all()
library(bslib)
library(reactable)
ui <- fluidPage(
theme = bs_theme(
version = 5,
preset = "bootstrap"
),
uiOutput(outputId = "custom_styles"),
edit_data_ui(id = "id"),
verbatimTextOutput("row_updated")
)
server <- function(input, output, session) {
rv <- reactiveValues(row_updated = NULL)
edited_r <- edit_data_server(
id = "id",
data_r = reactive(data.frame(
row_id = 1:12,
Month = month.name,
Values = 1:12,
Comment = letters[1:12]
)),
add = TRUE,
var_edit = c("Month", "Values", "Comment"),
reactable_options = list(
pagination = FALSE,
compact = TRUE,
columns = list(row_id = colDef(show = FALSE)),
rowClass = function(index) {
paste0("table-row-", index)
}
),
callback_add = function(data, row) {
print(row)
return(TRUE)
},
callback_delete = function(data, row) {
print(row)
return(TRUE)
},
callback_update = function(data, row) {
print(row)
rv$row_updated <- row$row_id
return(TRUE)
}
)
output$row_updated <- renderPrint({
paste("Last row updated:", rv$row_updated)
})
output$custom_styles <- renderUI({
req(rv$row_updated)
tags$style(sprintf(
".table-row-%s { background: #FE2E2E; transition: background 1s cubic-bezier(0.785, 0.135, 0.15, 0.86); color: white; }",
rv$row_updated
))
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/edit_data-callback_update.R
================================================
library(shiny)
library(datamods)
library(bslib)
library(reactable)
ui <- fluidPage(
theme = bs_theme(
version = 5
),
edit_data_ui(id = "id"),
verbatimTextOutput("result")
)
server <- function(input, output, session) {
edited_r <- edit_data_server(
id = "id",
data_r = reactive(data.frame(Month = month.name, Values = 1:12)),
add = TRUE,
callback_update = function(data, row) {
print(data)
print(row)
if (!row$Month %in% month.name)
return(FALSE)
if (row$Values > 20) {
shinybusy::notify_warning("Value must be equal or inferior to 20")
return(FALSE)
}
# else update data
return(TRUE)
}
)
output$result <- renderPrint({
str(edited_r())
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/edit_data.R
================================================
library(shiny)
library(datamods)
library(bslib)
library(reactable)
ui <- fluidPage(
theme = bs_theme(
version = 5
),
tags$h2("Edit data", align = "center"),
edit_data_ui(id = "id"),
verbatimTextOutput("result")
)
server <- function(input, output, session) {
edited_r <- edit_data_server(
id = "id",
data_r = reactive(demo_edit),
add = TRUE,
update = TRUE,
delete = TRUE,
download_csv = TRUE,
download_excel = TRUE,
file_name_export = "datas",
# var_edit = c("name", "job", "credit_card_provider", "credit_card_security_code"),
var_mandatory = c("name", "job"),
var_labels = list(
name = "Name",
credit_card_security_code = "Credit card security code",
date_obtained = "Date obtained",
contactless_card = "Contactless Card",
credit_card_provider = "Credit card provider"
),
add_default_values = list(
name = "Please enter your name here",
date_obtained = Sys.Date()
),
n_column = 2,
modal_size = "l",
modal_easy_close = TRUE,
reactable_options = list(
defaultColDef = colDef(filterable = TRUE),
selection = "single",
columns = list(
name = colDef(name = "Name", style = list(fontWeight = "bold")),
credit_card_security_code = colDef(name = "Credit card security code"),
date_obtained = colDef(name = "Date obtained", format = colFormat(date = TRUE)),
contactless_card = colDef(
name = "Contactless Card",
cell = htmlwidgets::JS(
"function(cellInfo) {
return cellInfo.value ? '\u2714\ufe0f Yes' : '\u274c No';
}"
)
),
credit_card_provider = colDef(
name = "Credit card provider",
style = htmlwidgets::JS(
"function(rowInfo) {
console.log(rowInfo);
var value = rowInfo.values['credit_card_provider'];
var color;
if (value == 'Mastercard') {
color = '#e06631';
} else if (value == 'VISA 16 digit') {
color = '#0c13cf';
} else if (value == 'American Express') {
color = '#4d8be8';
} else if (value == 'JCB 16 digit') {
color = '#23c45e';
} else {
color = '#777'
}
return {color: color, fontWeight: 'bold'}
}"
)
)
),
bordered = TRUE,
compact = TRUE,
searchable = TRUE,
highlight = TRUE
)
)
output$result <- renderPrint({
str(edited_r())
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/filter_data-basic.R
================================================
library(shiny)
library(datamods)
ui <- fluidPage(
tags$h2("Filter data.frame"),
fluidRow(
column(
width = 3,
filter_data_ui("filtering", max_height = "500px")
),
column(
width = 9,
reactable::reactableOutput(outputId = "table"),
tags$b("Code dplyr:"),
verbatimTextOutput(outputId = "code_dplyr"),
tags$b("Expression:"),
verbatimTextOutput(outputId = "code"),
tags$b("Filtered data:"),
verbatimTextOutput(outputId = "res_str")
)
)
)
server <- function(input, output, session) {
res_filter <- filter_data_server(
id = "filtering",
data = reactive(data.frame(
varchar = month.name,
varnum = 1:12,
vardate = Sys.Date() + 1:12
)),
vars = reactive(list(
"Variable character" = "varchar",
"Variable date" = "vardate",
"Variable numeric" = "varnum"
)),
drop_ids = FALSE
)
output$table <- reactable::renderReactable({
reactable::reactable(res_filter$filtered(), pagination = FALSE)
})
output$code_dplyr <- renderPrint({
res_filter$code()
})
output$code <- renderPrint({
res_filter$expr()
})
output$res_str <- renderPrint({
str(res_filter$filtered())
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/filter_data.R
================================================
library(shiny)
library(shinyWidgets)
library(datamods)
library(MASS)
# Add some NAs to mpg
mtcars_na <- mtcars
mtcars_na[] <- lapply(
X = mtcars_na,
FUN = function(x) {
x[sample.int(n = length(x), size = sample(5:10, 1))] <- NA
x
}
)
datetime <- data.frame(
date = seq(Sys.Date(), by = "day", length.out = 300),
datetime = seq(Sys.time(), by = "hour", length.out = 300),
num = sample.int(1e5, 300)
)
one_column_numeric <- data.frame(
var1 = rnorm(100)
)
ui <- fluidPage(
tags$h2("Filter data.frame"),
actionButton("saveFilterButton","Save Filter Values"),
actionButton("loadFilterButton","Load Filter Values"),
radioButtons(
inputId = "dataset",
label = "Data:",
choices = c(
"iris",
"mtcars",
"mtcars_na",
"Cars93",
"datetime",
"one_column_numeric"
),
inline = TRUE
),
fluidRow(
column(
width = 3,
filter_data_ui("filtering", max_height = "500px")
),
column(
width = 9,
progressBar(
id = "pbar", value = 100,
total = 100, display_pct = TRUE
),
reactable::reactableOutput(outputId = "table"),
tags$b("Code dplyr:"),
verbatimTextOutput(outputId = "code_dplyr"),
tags$b("Expression:"),
verbatimTextOutput(outputId = "code"),
tags$b("Filtered data:"),
verbatimTextOutput(outputId = "res_str")
)
)
)
server <- function(input, output, session) {
savedFilterValues <- reactiveVal()
data <- reactive({
get(input$dataset)
})
vars <- reactive({
if (identical(input$dataset, "mtcars")) {
setNames(as.list(names(mtcars)[1:5]), c(
"Miles/(US) gallon",
"Number of cylinders",
"Displacement (cu.in.)",
"Gross horsepower",
"Rear axle ratio"
))
} else {
NULL
}
})
observeEvent(input$saveFilterButton,{
savedFilterValues <<- res_filter$values()
},ignoreInit = T)
defaults <- reactive({
input$loadFilterButton
savedFilterValues
})
res_filter <- filter_data_server(
id = "filtering",
data = data,
name = reactive(input$dataset),
vars = vars,
defaults = defaults,
widget_num = "slider",
widget_date = "slider",
label_na = "Missing"
)
observeEvent(res_filter$filtered(), {
updateProgressBar(
session = session, id = "pbar",
value = nrow(res_filter$filtered()), total = nrow(data())
)
})
output$table <- reactable::renderReactable({
reactable::reactable(res_filter$filtered())
})
output$code_dplyr <- renderPrint({
res_filter$code()
})
output$code <- renderPrint({
res_filter$expr()
})
output$res_str <- renderPrint({
str(res_filter$filtered())
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/from-copypaste.R
================================================
library(shiny)
library(datamods)
ui <- fluidPage(
tags$h3("Import data with copy & paste"),
fluidRow(
column(
width = 4,
import_copypaste_ui("myid")
),
column(
width = 8,
tags$b("Import status:"),
verbatimTextOutput(outputId = "status"),
tags$b("Name:"),
verbatimTextOutput(outputId = "name"),
tags$b("Data:"),
verbatimTextOutput(outputId = "data")
)
)
)
server <- function(input, output, session) {
imported <- import_copypaste_server("myid")
output$status <- renderPrint({
imported$status()
})
output$name <- renderPrint({
imported$name()
})
output$data <- renderPrint({
imported$data()
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/from-file.R
================================================
library(shiny)
library(datamods)
ui <- fluidPage(
# theme = bslib::bs_theme(version = 5L),
# theme = bslib::bs_theme(version = 5L, preset = "bootstrap"),
tags$h3("Import data from a file"),
fluidRow(
column(
width = 4,
import_file_ui(
id = "myid",
file_extensions = c(".csv", ".txt", ".xls", ".xlsx", ".json"),
layout_params = "inline" # or "dropdown"
)
),
column(
width = 8,
tags$b("Import status:"),
verbatimTextOutput(outputId = "status"),
tags$b("Name:"),
verbatimTextOutput(outputId = "name"),
tags$b("Code:"),
verbatimTextOutput(outputId = "code"),
tags$b("Data:"),
verbatimTextOutput(outputId = "data")
)
)
)
server <- function(input, output, session) {
imported <- import_file_server(
id = "myid",
# Custom functions to read data
read_fns = list(
xls = function(file, sheet, skip, encoding) {
readxl::read_xls(path = file, sheet = sheet, skip = skip)
},
json = function(file) {
jsonlite::read_json(file, simplifyVector = TRUE)
}
),
show_data_in = "modal"
)
output$status <- renderPrint({
imported$status()
})
output$name <- renderPrint({
imported$name()
})
output$code <- renderPrint({
imported$code()
})
output$data <- renderPrint({
imported$data()
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/from-globalenv.R
================================================
if (interactive()) {
library(shiny)
library(datamods)
# Create some data.frames
my_df <- data.frame(
variable1 = sample(letters, 20, TRUE),
variable2 = sample(1:100, 20, TRUE)
)
results_analysis <- data.frame(
id = sample(letters, 20, TRUE),
measure = sample(1:100, 20, TRUE),
response = sample(1:100, 20, TRUE)
)
# Application
ui <- fluidPage(
fluidRow(
column(
width = 4,
import_globalenv_ui("myid")
),
column(
width = 8,
tags$b("Import status:"),
verbatimTextOutput(outputId = "status"),
tags$b("Name:"),
verbatimTextOutput(outputId = "name"),
tags$b("Data:"),
verbatimTextOutput(outputId = "data")
)
)
)
server <- function(input, output, session) {
imported <- import_globalenv_server("myid")
output$status <- renderPrint({
imported$status()
})
output$name <- renderPrint({
imported$name()
})
output$data <- renderPrint({
imported$data()
})
}
shinyApp(ui, server)
}
================================================
FILE: examples/from-googlesheets.R
================================================
library(shiny)
library(datamods)
ui <- fluidPage(
tags$h3("Import data from Googlesheets"),
fluidRow(
column(
width = 4,
import_googlesheets_ui("myid")
),
column(
width = 8,
tags$b("Import status:"),
verbatimTextOutput(outputId = "status"),
tags$b("Name:"),
verbatimTextOutput(outputId = "name"),
tags$b("Data:"),
verbatimTextOutput(outputId = "data")
)
)
)
server <- function(input, output, session) {
imported <- import_googlesheets_server("myid")
output$status <- renderPrint({
imported$status()
})
output$name <- renderPrint({
imported$name()
})
output$data <- renderPrint({
imported$data()
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/from-url.R
================================================
library(shiny)
library(datamods)
ui <- fluidPage(
tags$h3("Import data from URL"),
fluidRow(
column(
width = 4,
import_url_ui("myid")
),
column(
width = 8,
tags$b("Import status:"),
verbatimTextOutput(outputId = "status"),
tags$b("Name:"),
verbatimTextOutput(outputId = "name"),
tags$b("Data:"),
verbatimTextOutput(outputId = "data")
)
)
)
server <- function(input, output, session) {
imported <- import_url_server(
"myid",
btn_show_data = FALSE,
return_class = "raw"
)
output$status <- renderPrint({
imported$status()
})
output$name <- renderPrint({
imported$name()
})
output$data <- renderPrint({
imported$data()
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/i18n.R
================================================
library(datamods)
# Use with an objet
my.translations <- list(
"Hello" = "Bonjour"
)
i18n("Hello", my.translations)
# Use with options()
options("i18n" = list(
"Hello" = "Bonjour"
))
i18n("Hello")
# With a package
options("datamods.i18n" = "fr")
i18n("Browse...", translations = i18n_translations("datamods"))
# If you call i18n() from within a function of your package
# you don't need second argument, e.g.:
# i18n("Browse...")
================================================
FILE: examples/modal-validation.R
================================================
library(shiny)
library(datamods)
if (requireNamespace("validate")) {
library(validate)
# Define some rules to be applied to data
myrules <- validator(
is.character(Manufacturer) | is.factor(Manufacturer),
is.character(Model) | is.factor(Model),
is_unique(Manufacturer, Model),
is.numeric(Price),
is.numeric(Min.Price),
is.numeric(Max.Price),
Price > 12, # we should use 0 for testing positivity, but that's for the example
!is.na(Luggage.room),
in_range(Cylinders, min = 4, max = 8),
Man.trans.avail %in% c("Yes", "No")
)
# Add some labels
label(myrules) <- c(
"Variable Manufacturer must be character",
"Variable Model must be character",
"Manufacturer X Model are unique",
"Variable Price must be numeric",
"Variable Min.Price must be numeric",
"Variable Max.Price must be numeric",
"Variable Price must be strictly positive",
"Luggage.room must not contain any missing values",
"Cylinders must be between 4 and 8",
"Man.trans.avail must be 'Yes' or 'No'"
)
# you can also add a description()
ui <- fluidPage(
fluidRow(
column(
width = 4,
checkboxGroupInput(
inputId = "from",
label = "From",
choices = c("env", "file", "copypaste", "googlesheets", "url"),
selected = c("file", "copypaste")
),
actionButton("launch_modal", "Launch modal window")
),
column(
width = 8,
tags$b("Imported data:"),
verbatimTextOutput(outputId = "name"),
verbatimTextOutput(outputId = "data")
)
)
)
server <- function(input, output, session) {
observeEvent(input$launch_modal, {
req(input$from)
import_modal(
id = "myid",
from = input$from,
title = "Import data to be used in application"
)
})
imported <- import_server(
id = "myid",
return_class = "tbl_df",
validation_opts = list(
# rules = validator(.file = system.file("extdata/rules.yaml", package = "datamods"))
rules = myrules
)
)
output$name <- renderPrint({
req(imported$name())
imported$name()
})
output$data <- renderPrint({
req(imported$data())
imported$data()
})
}
if (interactive())
shinyApp(ui, server)
}
================================================
FILE: examples/modal.R
================================================
library(shiny)
library(datamods)
ui <- fluidPage(
# Try with different Bootstrap version
theme = bslib::bs_theme(version = 5, preset = "bootstrap"),
fluidRow(
column(
width = 4,
checkboxGroupInput(
inputId = "from",
label = "From",
choices = c("env", "file", "copypaste", "googlesheets", "url"),
selected = c("file", "copypaste")
),
actionButton("launch_modal", "Launch modal window")
),
column(
width = 8,
tags$b("Imported data:"),
verbatimTextOutput(outputId = "name"),
verbatimTextOutput(outputId = "data"),
verbatimTextOutput(outputId = "str_data")
)
)
)
server <- function(input, output, session) {
observeEvent(input$launch_modal, {
req(input$from)
import_modal(
id = "myid",
from = input$from,
title = "Import data to be used in application"
)
})
imported <- import_server("myid", return_class = "tbl_df")
output$name <- renderPrint({
req(imported$name())
imported$name()
})
output$data <- renderPrint({
req(imported$data())
imported$data()
})
output$str_data <- renderPrint({
req(imported$data())
str(imported$data())
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/sample.R
================================================
library(shiny)
library(datamods)
library(reactable)
ui <- fluidPage(
tags$h2("Sampling"),
fluidRow(
column(
width = 3,
sample_ui("myID")
),
column(
width = 9,
reactableOutput("table")
)
)
)
server <- function(input, output, session) {
result_sample <- sample_server("myID", reactive(iris))
output$table <- renderReactable({
table_sample <- reactable(
data = result_sample(),
defaultColDef = colDef(
align = "center"
),
borderless = TRUE,
highlight = TRUE,
striped = TRUE
)
return(table_sample)
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/select-group-default.R
================================================
# Default -----------------------------------------------------------------
library(shiny)
library(datamods)
library(shinyWidgets)
ui <- fluidPage(
# theme = bslib::bs_theme(version = 5L),
fluidRow(
column(
width = 10, offset = 1,
tags$h3("Filter data with select group module"),
shinyWidgets::panel(
select_group_ui(
id = "my-filters",
params = list(
list(inputId = "Manufacturer", label = "Manufacturer:"),
list(inputId = "Type", label = "Type:"),
list(inputId = "AirBags", label = "AirBags:"),
list(inputId = "DriveTrain", label = "DriveTrain:")
), vs_args = list(disableSelectAll = FALSE)
),
status = "primary"
),
reactable::reactableOutput(outputId = "table"),
tags$b("Inputs values:"),
verbatimTextOutput("inputs")
)
)
)
server <- function(input, output, session) {
res_mod <- select_group_server(
id = "my-filters",
data = reactive(MASS::Cars93),
vars = reactive(c("Manufacturer", "Type", "AirBags", "DriveTrain"))
)
output$table <- reactable::renderReactable({
reactable::reactable(res_mod())
})
output$inputs <- renderPrint({
attr(res_mod(), "inputs")
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/select-group-selected.R
================================================
# Selected value --------------------------------------------------------------------
library(shiny)
library(datamods)
ui <- fluidPage(
select_group_ui(
id = "my-filters",
params = list(
list(inputId = "Manufacturer", label = "Manufacturer:"),
list(inputId = "Type", label = "Type:")
),
vs_args = list(
disableSelectAll = FALSE
)
),
actionButton("set_sel", "Set Manufacturer=Acura"),
verbatimTextOutput("res")
)
server <- function(input, output, session) {
# We use a reactiveValue so that it can be updated
rv <- reactiveValues(selected = list(Manufacturer = "Audi")) # for init
res_r <- select_group_server(
id = "my-filters",
data = reactive(MASS::Cars93),
vars = reactive(c("Manufacturer", "Type")),
selected_r = reactive(rv$selected)
)
output$res <- renderPrint({
res_r()
})
observeEvent(input$set_sel, {
rv$selected <- list(Manufacturer = "Acura")
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/select-group-subset.R
================================================
# Subset data -------------------------------------------------------------
library(shiny)
library(datamods)
library(shinyWidgets)
ui <- fluidPage(
fluidRow(
column(
width = 10, offset = 1,
tags$h3("Filter data with select group module"),
panel(
pickerInput(
inputId = "car_select",
choices = unique(MASS::Cars93$Manufacturer),
options = list(
`live-search` = TRUE,
title = "None selected"
)
),
select_group_ui(
id = "my-filters",
params = list(
list(inputId = "Manufacturer", label = "Manufacturer:"),
list(inputId = "Type", label = "Type:"),
list(inputId = "AirBags", label = "AirBags:"),
list(inputId = "DriveTrain", label = "DriveTrain:")
)
),
status = "primary"
),
reactable::reactableOutput(outputId = "table")
)
)
)
server <- function(input, output, session) {
cars_r <- reactive({
subset(MASS::Cars93, Manufacturer %in% input$car_select)
})
res_mod <- select_group_server(
id = "my-filters",
data = cars_r,
vars = c("Manufacturer", "Type", "AirBags", "DriveTrain")
)
output$table <- reactable::renderReactable({
reactable::reactable(res_mod())
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/select-group-vars.R
================================================
# Select variables --------------------------------------------------------
library(shiny)
library(datamods)
library(shinyWidgets)
ui <- fluidPage(
fluidRow(
column(
width = 10, offset = 1,
tags$h3("Filter data with select group module"),
panel(
checkboxGroupInput(
inputId = "vars",
label = "Variables to use:",
choices = c("Manufacturer", "Type", "AirBags", "DriveTrain"),
selected = c("Manufacturer", "Type", "AirBags", "DriveTrain"),
inline = TRUE
),
select_group_ui(
id = "my-filters",
params = list(
list(inputId = "Manufacturer", label = "Manufacturer:"),
list(inputId = "Type", label = "Type:"),
list(inputId = "AirBags", label = "AirBags:"),
list(inputId = "DriveTrain", label = "DriveTrain:")
),
inline = TRUE
),
status = "primary"
),
reactable::reactableOutput(outputId = "table")
)
)
)
server <- function(input, output, session) {
vars_r <- reactive({
input$vars
})
res_mod <- select_group_server(
id = "my-filters",
data = MASS::Cars93,
vars = vars_r
)
output$table <- reactable::renderReactable({
reactable::reactable(res_mod())
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/show_data.R
================================================
library(shiny)
library(datamods)
ui <- fluidPage(
theme = bslib::bs_theme(version = 5L),
shinyWidgets::html_dependency_winbox(),
actionButton(
inputId = "show1",
label = "Show data in popup",
icon = icon("eye")
),
actionButton(
inputId = "show2",
label = "Show data in modal",
icon = icon("eye")
),
actionButton(
inputId = "show3",
label = "Show data without classes",
icon = icon("eye")
),
actionButton(
inputId = "show4",
label = "Show data in Winbox",
icon = icon("eye")
)
)
server <- function(input, output, session) {
observeEvent(input$show1, {
show_data(MASS::Cars93, title = "MASS::Cars93 dataset", type = "popup")
})
observeEvent(input$show2, {
show_data(MASS::Cars93, title = "MASS::Cars93 dataset", type = "modal")
})
observeEvent(input$show3, {
show_data(
data = MASS::Cars93,
title = "MASS::Cars93 dataset",
show_classes = FALSE,
options = list(pagination = 10),
type = "modal"
)
})
observeEvent(input$show4, {
show_data(
MASS::Cars93,
title = "MASS::Cars93 dataset",
type = "winbox",
wbOptions = shinyWidgets::wbOptions(background = "forestgreen")
)
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/update_factor.R
================================================
library(shiny)
library(datamods)
library(ggplot2)
ui <- fluidPage(
theme = bslib::bs_theme(version = 5L, preset = "bootstrap"),
shinyWidgets::html_dependency_winbox(),
tags$h2("Reorder the Levels of a Factor"),
fluidRow(
column(
width = 6,
update_factor_ui("id"),
actionButton("modal", "Or click here to open a modal to update factor's level"),
tags$br(), tags$br(),
actionButton("winbox", "Or click here to open a WinBox to create a column")
),
column(
width = 6,
selectInput(
"var",
label = "Variable to plot:",
choices = NULL
),
plotOutput("plot"),
verbatimTextOutput("res")
)
)
)
server <- function(input, output, session) {
rv <- reactiveValues(data = MASS::Cars93[c(1, 2, 3, 9, 10, 11, 16, 26, 27)])
observe(
updateSelectInput(inputId = "var", choices = names(rv$data))
)
# Inline mode
data_inline_r <- update_factor_server(
id = "id",
data_r = reactive(rv$data)
)
observeEvent(data_inline_r(), rv$data <- data_inline_r())
# modal window mode
observeEvent(input$modal, modal_update_factor("modal"))
data_modal_r <- update_factor_server(
id = "modal",
data_r = reactive(rv$data)
)
observeEvent(data_modal_r(), {
shiny::removeModal()
rv$data <- data_modal_r()
})
# winbox mode
observeEvent(input$winbox, winbox_update_factor("winbox"))
data_winbox_r <- update_factor_server(
id = "winbox",
data_r = reactive(rv$data)
)
observeEvent(data_winbox_r(), rv$data <- data_winbox_r())
# Plot results
output$plot <- renderPlot({
req(input$var, rv$data)
ggplot(rv$data) +
aes(x = !!sym(input$var)) +
geom_bar()
})
# Show results
output$res <- renderPrint({
data <- req(rv$data)
str(data)
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: examples/validation.R
================================================
library(datamods)
library(shiny)
if (requireNamespace("validate")) {
library(validate)
# Define some rules to be applied to data
myrules <- validator(
is.character(Manufacturer) | is.factor(Manufacturer),
is.numeric(Price),
Price > 12, # we should use 0 for testing positivity, but that's for the example
!is.na(Luggage.room),
in_range(Cylinders, min = 4, max = 8),
Man.trans.avail %in% c("Yes", "No")
)
# Add some labels
label(myrules) <- c(
"Variable Manufacturer must be character",
"Variable Price must be numeric",
"Variable Price must be strictly positive",
"Luggage.room must not contain any missing values",
"Cylinders must be between 4 and 8",
"Man.trans.avail must be 'Yes' or 'No'"
)
# you can also add a description()
ui <- fluidPage(
tags$h2("Validation"),
fluidRow(
column(
width = 4,
radioButtons(
inputId = "dataset",
label = "Choose dataset:",
choices = c("mtcars", "MASS::Cars93")
),
tags$p("Dropdown example:"),
validation_ui("validation1"),
tags$br(),
tags$p("Inline example:"),
validation_ui("validation2", display = "inline")
),
column(
width = 8,
tags$b("Status:"),
verbatimTextOutput("status"),
tags$b("Details:"),
verbatimTextOutput("details")
)
)
)
server <- function(input, output, session) {
dataset <- reactive({
if (input$dataset == "mtcars") {
mtcars
} else {
MASS::Cars93
}
})
results <- validation_server(
id = "validation1",
data = dataset,
n_row = ~ . > 20, # more than 20 rows
n_col = ~ . >= 3, # at least 3 columns
rules = myrules
)
validation_server(
id = "validation2",
data = dataset,
n_row = ~ . > 20, # more than 20 rows
n_col = ~ . >= 3, # at least 3 columns
rules = myrules
)
output$status <- renderPrint(results$status())
output$details <- renderPrint(results$details())
}
if (interactive())
shinyApp(ui, server)
}
================================================
FILE: examples/variables.R
================================================
library(shiny)
library(datamods)
testdata <- data.frame(
date_as_char = as.character(Sys.Date() + 0:9),
date_as_num = as.numeric(Sys.Date() + 0:9),
datetime_as_char = as.character(Sys.time() + 0:9 * 3600*24),
datetime_as_num = as.numeric(Sys.time() + 0:9 * 3600*24),
num_as_char = as.character(1:10),
char = month.name[1:10],
char_na = c("A", "A", "B", NA, "B", "A", NA, "B", "A", "B"),
stringsAsFactors = FALSE
)
ui <- fluidPage(
theme = bslib::bs_theme(version = 5L, preset = "bootstrap"),
tags$h3("Select, rename and convert variables"),
fluidRow(
column(
width = 6,
# radioButtons()
update_variables_ui("vars")
),
column(
width = 6,
tags$b("original data:"),
verbatimTextOutput("original"),
verbatimTextOutput("original_str"),
tags$b("Modified data:"),
verbatimTextOutput("modified"),
verbatimTextOutput("modified_str")
)
)
)
server <- function(input, output, session) {
updated_data <- update_variables_server(
id = "vars",
data = reactive(testdata),
return_data_on_init = FALSE
)
output$original <- renderPrint({
testdata
})
output$original_str <- renderPrint({
str(testdata)
})
output$modified <- renderPrint({
updated_data()
})
output$modified_str <- renderPrint({
str(updated_data())
})
}
if (interactive())
shinyApp(ui, server)
================================================
FILE: inst/assets/css/datamods.css
================================================
/*!
* Copyright (c) 2020 dreamRs
*
* datamods, CSS styles
* https://github.com/dreamRs/datamods
*
* @version 0.0.1
*/
.show-block {
display: block !important;
}
.show-inline {
display: inline !important;
}
.hidden {
display: none !important;
}
.invisible {
visibility: hidden;
}
.container-rule {
position: relative;
text-align: center;
height: 25px;
margin-bottom: 5px;
}
.horizontal-rule {
position: absolute;
top: 11px;
right: 0;
left: 0;
background-color: #d0cfcf;
height: 1px;
z-index: 100;
margin: 0;
border: none;
}
.label-rule {
background: #FFF;
opacity: 1;
z-index: 101;
background-color: #FFF;
position: relative;
padding: 0 10px 0 10px;
}
.datamods-table-container {
overflow: auto;
word-break: keep-all;
white-space: nowrap;
}
.datamods-table-container > .table {
margin-bottom: 0 !important;
}
.datamods-file-import {
display: grid;
grid-template-columns: auto 50px;
grid-column-gap: 10px;
}
.datamods-dt-nowrap {
word-break: keep-all;
white-space: nowrap;
}
/* validation */
.datamods-validation-results {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 1fr;
height: 50px;
line-height: 50px;
font-size: large;
}
.datamods-validation-summary {
font-weight: bold;
text-align: center;
}
.datamods-validation-item {
font-size: larger;
}
/* from esquisse */
.btn-column-discrete {
background-color: #EF562D;
color: #FFFFFF;
}
.btn-column-continuous {
background-color: #0C4C8A;
color: #FFFFFF;
}
.btn-column-datetime {
background-color: #97D5E0;
color: #FFFFFF;
}
.btn-column-id {
background-color: #848484;
color: #FFFFFF;
}
.btn-column-other {
background-color: #2E2E2E;
color: #FFFFFF;
}
================================================
FILE: inst/assets/js/datamods.js
================================================
/*!
* Copyright (c) 2020 dreamRs
*
* datamods, JavaScript utilities
* https://github.com/dreamRs/datamods
*
* @version 0.0.1
*/
/*jshint
jquery:true
*/
/*global Shiny */
// Block or unblock an input widget
Shiny.addCustomMessageHandler("datamods-toggleWidget", function(data) {
$("#" + data.id).prop("disabled", !data.enable);
if ($("#" + data.id).hasClass("selectpicker")) {
$("#" + data.id).selectpicker("refresh");
}
});
// Hide or show UI component
Shiny.addCustomMessageHandler("datamods-showUI", function(data) {
var sel = data.selector;
if (data.hasOwnProperty("id")) {
sel = "#" + $.escapeSelector(data.id);
}
if (data.inline) {
$(sel).addClass("show-inline");
$(sel).removeClass("hidden");
} else {
$(sel).addClass("show-block");
$(sel).removeClass("hidden");
}
});
Shiny.addCustomMessageHandler("datamods-hideUI", function(data) {
var sel = data.selector;
if (data.hasOwnProperty("id")) {
sel = "#" + $.escapeSelector(data.id);
}
if (data.inline) {
$(sel).addClass("hidden");
$(sel).removeClass("show-inline");
} else {
$(sel).addClass("hidden");
$(sel).removeClass("show-block");
}
});
function fadeTab(data) {
var tabId = $("#" + data.id).attr("data-tabsetid");
$("#" + data.id)
.parent()
.find(".tab-pane")
.each(function(index) {
if ($(this).parent().attr("data-tabsetid") == tabId) {
$( this ).addClass("fade");
if (index < 1) {
$( this ).addClass("in");
}
}
});
}
function updateTabLabel(data) {
var el = $("#" + data.id).find("[data-value='" + data.value + "']");
if (typeof el[0] != "undefined") {
$(el[0]).html(data.label);
}
}
Shiny.addCustomMessageHandler("datamods-updateTabLabel", updateTabLabel);
function disableTab(data) {
var el = $("#" + data.id).find("[data-value='" + data.value + "']");
if (typeof el[0] != "undefined") {
$(el[0]).removeAttr("data-toggle");
$(el[0]).parent().addClass("disabled");
$(el[0]).addClass("disabled");
}
}
Shiny.addCustomMessageHandler("datamods-disableTab", disableTab);
function enableTab(data) {
var el = $("#" + data.id).find("[data-value='" + data.value + "']");
if (typeof el[0] != "undefined") {
$(el[0]).attr("data-toggle", "tab");
$(el[0]).parent().removeClass("disabled");
$(el[0]).removeClass("disabled");
}
}
Shiny.addCustomMessageHandler("datamods-enableTab", enableTab);
================================================
FILE: inst/extdata/mtcars.csv
================================================
mpg,cyl,disp,hp,drat,wt,qsec,vs,am,gear,carb
21,6,160,110,3.9,2.62,16.46,0,1,4,4
21,6,160,110,3.9,2.875,17.02,0,1,4,4
22.8,4,108,93,3.85,2.32,18.61,1,1,4,1
21.4,6,258,110,3.08,3.215,19.44,1,0,3,1
18.7,8,360,175,3.15,3.44,17.02,0,0,3,2
18.1,6,225,105,2.76,3.46,20.22,1,0,3,1
14.3,8,360,245,3.21,3.57,15.84,0,0,3,4
24.4,4,146.7,62,3.69,3.19,20,1,0,4,2
22.8,4,140.8,95,3.92,3.15,22.9,1,0,4,2
19.2,6,167.6,123,3.92,3.44,18.3,1,0,4,4
17.8,6,167.6,123,3.92,3.44,18.9,1,0,4,4
16.4,8,275.8,180,3.07,4.07,17.4,0,0,3,3
17.3,8,275.8,180,3.07,3.73,17.6,0,0,3,3
15.2,8,275.8,180,3.07,3.78,18,0,0,3,3
10.4,8,472,205,2.93,5.25,17.98,0,0,3,4
10.4,8,460,215,3,5.424,17.82,0,0,3,4
14.7,8,440,230,3.23,5.345,17.42,0,0,3,4
32.4,4,78.7,66,4.08,2.2,19.47,1,1,4,1
30.4,4,75.7,52,4.93,1.615,18.52,1,1,4,2
33.9,4,71.1,65,4.22,1.835,19.9,1,1,4,1
21.5,4,120.1,97,3.7,2.465,20.01,1,0,3,1
15.5,8,318,150,2.76,3.52,16.87,0,0,3,2
15.2,8,304,150,3.15,3.435,17.3,0,0,3,2
13.3,8,350,245,3.73,3.84,15.41,0,0,3,4
19.2,8,400,175,3.08,3.845,17.05,0,0,3,2
27.3,4,79,66,4.08,1.935,18.9,1,1,4,1
26,4,120.3,91,4.43,2.14,16.7,0,1,5,2
30.4,4,95.1,113,3.77,1.513,16.9,1,1,5,2
15.8,8,351,264,4.22,3.17,14.5,0,1,5,4
19.7,6,145,175,3.62,2.77,15.5,0,1,5,6
15,8,301,335,3.54,3.57,14.6,0,1,5,8
21.4,4,121,109,4.11,2.78,18.6,1,1,4,2
================================================
FILE: inst/extdata/mtcars.json
================================================
[{"mpg":21,"cyl":6,"disp":160,"hp":110,"drat":3.9,"wt":2.62,"qsec":16.46,"vs":0,"am":1,"gear":4,"carb":4,"_row":"Mazda RX4"},{"mpg":21,"cyl":6,"disp":160,"hp":110,"drat":3.9,"wt":2.875,"qsec":17.02,"vs":0,"am":1,"gear":4,"carb":4,"_row":"Mazda RX4 Wag"},{"mpg":22.8,"cyl":4,"disp":108,"hp":93,"drat":3.85,"wt":2.32,"qsec":18.61,"vs":1,"am":1,"gear":4,"carb":1,"_row":"Datsun 710"},{"mpg":21.4,"cyl":6,"disp":258,"hp":110,"drat":3.08,"wt":3.215,"qsec":19.44,"vs":1,"am":0,"gear":3,"carb":1,"_row":"Hornet 4 Drive"},{"mpg":18.7,"cyl":8,"disp":360,"hp":175,"drat":3.15,"wt":3.44,"qsec":17.02,"vs":0,"am":0,"gear":3,"carb":2,"_row":"Hornet Sportabout"},{"mpg":18.1,"cyl":6,"disp":225,"hp":105,"drat":2.76,"wt":3.46,"qsec":20.22,"vs":1,"am":0,"gear":3,"carb":1,"_row":"Valiant"},{"mpg":14.3,"cyl":8,"disp":360,"hp":245,"drat":3.21,"wt":3.57,"qsec":15.84,"vs":0,"am":0,"gear":3,"carb":4,"_row":"Duster 360"},{"mpg":24.4,"cyl":4,"disp":146.7,"hp":62,"drat":3.69,"wt":3.19,"qsec":20,"vs":1,"am":0,"gear":4,"carb":2,"_row":"Merc 240D"},{"mpg":22.8,"cyl":4,"disp":140.8,"hp":95,"drat":3.92,"wt":3.15,"qsec":22.9,"vs":1,"am":0,"gear":4,"carb":2,"_row":"Merc 230"},{"mpg":19.2,"cyl":6,"disp":167.6,"hp":123,"drat":3.92,"wt":3.44,"qsec":18.3,"vs":1,"am":0,"gear":4,"carb":4,"_row":"Merc 280"},{"mpg":17.8,"cyl":6,"disp":167.6,"hp":123,"drat":3.92,"wt":3.44,"qsec":18.9,"vs":1,"am":0,"gear":4,"carb":4,"_row":"Merc 280C"},{"mpg":16.4,"cyl":8,"disp":275.8,"hp":180,"drat":3.07,"wt":4.07,"qsec":17.4,"vs":0,"am":0,"gear":3,"carb":3,"_row":"Merc 450SE"},{"mpg":17.3,"cyl":8,"disp":275.8,"hp":180,"drat":3.07,"wt":3.73,"qsec":17.6,"vs":0,"am":0,"gear":3,"carb":3,"_row":"Merc 450SL"},{"mpg":15.2,"cyl":8,"disp":275.8,"hp":180,"drat":3.07,"wt":3.78,"qsec":18,"vs":0,"am":0,"gear":3,"carb":3,"_row":"Merc 450SLC"},{"mpg":10.4,"cyl":8,"disp":472,"hp":205,"drat":2.93,"wt":5.25,"qsec":17.98,"vs":0,"am":0,"gear":3,"carb":4,"_row":"Cadillac Fleetwood"},{"mpg":10.4,"cyl":8,"disp":460,"hp":215,"drat":3,"wt":5.424,"qsec":17.82,"vs":0,"am":0,"gear":3,"carb":4,"_row":"Lincoln Continental"},{"mpg":14.7,"cyl":8,"disp":440,"hp":230,"drat":3.23,"wt":5.345,"qsec":17.42,"vs":0,"am":0,"gear":3,"carb":4,"_row":"Chrysler Imperial"},{"mpg":32.4,"cyl":4,"disp":78.7,"hp":66,"drat":4.08,"wt":2.2,"qsec":19.47,"vs":1,"am":1,"gear":4,"carb":1,"_row":"Fiat 128"},{"mpg":30.4,"cyl":4,"disp":75.7,"hp":52,"drat":4.93,"wt":1.615,"qsec":18.52,"vs":1,"am":1,"gear":4,"carb":2,"_row":"Honda Civic"},{"mpg":33.9,"cyl":4,"disp":71.1,"hp":65,"drat":4.22,"wt":1.835,"qsec":19.9,"vs":1,"am":1,"gear":4,"carb":1,"_row":"Toyota Corolla"},{"mpg":21.5,"cyl":4,"disp":120.1,"hp":97,"drat":3.7,"wt":2.465,"qsec":20.01,"vs":1,"am":0,"gear":3,"carb":1,"_row":"Toyota Corona"},{"mpg":15.5,"cyl":8,"disp":318,"hp":150,"drat":2.76,"wt":3.52,"qsec":16.87,"vs":0,"am":0,"gear":3,"carb":2,"_row":"Dodge Challenger"},{"mpg":15.2,"cyl":8,"disp":304,"hp":150,"drat":3.15,"wt":3.435,"qsec":17.3,"vs":0,"am":0,"gear":3,"carb":2,"_row":"AMC Javelin"},{"mpg":13.3,"cyl":8,"disp":350,"hp":245,"drat":3.73,"wt":3.84,"qsec":15.41,"vs":0,"am":0,"gear":3,"carb":4,"_row":"Camaro Z28"},{"mpg":19.2,"cyl":8,"disp":400,"hp":175,"drat":3.08,"wt":3.845,"qsec":17.05,"vs":0,"am":0,"gear":3,"carb":2,"_row":"Pontiac Firebird"},{"mpg":27.3,"cyl":4,"disp":79,"hp":66,"drat":4.08,"wt":1.935,"qsec":18.9,"vs":1,"am":1,"gear":4,"carb":1,"_row":"Fiat X1-9"},{"mpg":26,"cyl":4,"disp":120.3,"hp":91,"drat":4.43,"wt":2.14,"qsec":16.7,"vs":0,"am":1,"gear":5,"carb":2,"_row":"Porsche 914-2"},{"mpg":30.4,"cyl":4,"disp":95.1,"hp":113,"drat":3.77,"wt":1.513,"qsec":16.9,"vs":1,"am":1,"gear":5,"carb":2,"_row":"Lotus Europa"},{"mpg":15.8,"cyl":8,"disp":351,"hp":264,"drat":4.22,"wt":3.17,"qsec":14.5,"vs":0,"am":1,"gear":5,"carb":4,"_row":"Ford Pantera L"},{"mpg":19.7,"cyl":6,"disp":145,"hp":175,"drat":3.62,"wt":2.77,"qsec":15.5,"vs":0,"am":1,"gear":5,"carb":6,"_row":"Ferrari Dino"},{"mpg":15,"cyl":8,"disp":301,"hp":335,"drat":3.54,"wt":3.57,"qsec":14.6,"vs":0,"am":1,"gear":5,"carb":8,"_row":"Maserati Bora"},{"mpg":21.4,"cyl":4,"disp":121,"hp":109,"drat":4.11,"wt":2.78,"qsec":18.6,"vs":1,"am":1,"gear":4,"carb":2,"_row":"Volvo 142E"}]
================================================
FILE: inst/extdata/mtcars_fr.csv
================================================
mpg;cyl;disp;hp;drat;wt;qsec;vs;am;gear;carb
21,0;6;160,0;110;3,90;2,620;16,46;0;1;4;4
21,0;6;160,0;110;3,90;2,875;17,02;0;1;4;4
22,8;4;108,0;93;3,85;2,320;18,61;1;1;4;1
21,4;6;258,0;110;3,08;3,215;19,44;1;0;3;1
18,7;8;360,0;175;3,15;3,440;17,02;0;0;3;2
18,1;6;225,0;105;2,76;3,460;20,22;1;0;3;1
14,3;8;360,0;245;3,21;3,570;15,84;0;0;3;4
24,4;4;146,7;62;3,69;3,190;20,00;1;0;4;2
22,8;4;140,8;95;3,92;3,150;22,90;1;0;4;2
19,2;6;167,6;123;3,92;3,440;18,30;1;0;4;4
17,8;6;167,6;123;3,92;3,440;18,90;1;0;4;4
16,4;8;275,8;180;3,07;4,070;17,40;0;0;3;3
17,3;8;275,8;180;3,07;3,730;17,60;0;0;3;3
15,2;8;275,8;180;3,07;3,780;18,00;0;0;3;3
10,4;8;472,0;205;2,93;5,250;17,98;0;0;3;4
10,4;8;460,0;215;3,00;5,424;17,82;0;0;3;4
14,7;8;440,0;230;3,23;5,345;17,42;0;0;3;4
32,4;4;78,7;66;4,08;2,200;19,47;1;1;4;1
30,4;4;75,7;52;4,93;1,615;18,52;1;1;4;2
33,9;4;71,1;65;4,22;1,835;19,90;1;1;4;1
21,5;4;120,1;97;3,70;2,465;20,01;1;0;3;1
15,5;8;318,0;150;2,76;3,520;16,87;0;0;3;2
15,2;8;304,0;150;3,15;3,435;17,30;0;0;3;2
13,3;8;350,0;245;3,73;3,840;15,41;0;0;3;4
19,2;8;400,0;175;3,08;3,845;17,05;0;0;3;2
27,3;4;79,0;66;4,08;1,935;18,90;1;1;4;1
26,0;4;120,3;91;4,43;2,140;16,70;0;1;5;2
30,4;4;95,1;113;3,77;1,513;16,90;1;1;5;2
15,8;8;351,0;264;4,22;3,170;14,50;0;1;5;4
19,7;6;145,0;175;3,62;2,770;15,50;0;1;5;6
15,0;8;301,0;335;3,54;3,570;14,60;0;1;5;8
21,4;4;121,0;109;4,11;2,780;18,60;1;1;4;2
================================================
FILE: inst/extdata/pop-fra-dep.txt
================================================
Code région Nom de la région Code département Nom du département Nombre d'arrondissements Nombre de cantons Nombre de communes Population municipale Population totale
84 Auvergne-Rhône-Alpes 01 Ain 4 23 393 643 350 659 180
32 Hauts-de-France 02 Aisne 5 21 800 534 490 546 527
84 Auvergne-Rhône-Alpes 03 Allier 3 19 317 337 988 347 035
93 Provence-Alpes-Côte d'Azur 04 Alpes-de-Haute-Provence 4 15 198 163 915 168 381
93 Provence-Alpes-Côte d'Azur 05 Hautes-Alpes 2 15 162 141 284 145 883
93 Provence-Alpes-Côte d'Azur 06 Alpes-Maritimes 2 27 163 1 083 310 1 097 496
84 Auvergne-Rhône-Alpes 07 Ardèche 3 17 335 325 712 334 688
44 Grand Est 08 Ardennes 4 19 449 273 579 280 032
76 Occitanie 09 Ariège 3 13 327 153 153 157 210
44 Grand Est 10 Aube 3 17 431 310 020 317 118
76 Occitanie 11 Aude 3 19 433 370 260 379 094
76 Occitanie 12 Aveyron 3 23 285 279 206 289 488
93 Provence-Alpes-Côte d'Azur 13 Bouches-du-Rhône 4 29 119 2 024 162 2 048 504
28 Normandie 14 Calvados 4 25 527 694 002 708 344
84 Auvergne-Rhône-Alpes 15 Cantal 3 15 246 145 143 150 185
75 Nouvelle-Aquitaine 16 Charente 3 19 366 352 335 361 539
75 Nouvelle-Aquitaine 17 Charente-Maritime 5 27 463 644 303 659 968
24 Centre-Val de Loire 18 Cher 3 19 287 304 256 311 456
75 Nouvelle-Aquitaine 19 Corrèze 3 19 280 241 464 249 135
94 Corse 2A Corse-du-Sud 2 11 124 157 249 159 768
94 Corse 2B Haute-Corse 3 15 236 177 689 180 465
27 Bourgogne-Franche-Comté 21 Côte-d'Or 3 23 700 533 819 545 798
53 Bretagne 22 Côtes-d'Armor 4 27 348 598 814 617 107
75 Nouvelle-Aquitaine 23 Creuse 2 15 256 118 638 122 133
75 Nouvelle-Aquitaine 24 Dordogne 4 25 505 413 606 424 095
27 Bourgogne-Franche-Comté 25 Doubs 3 19 573 539 067 552 643
84 Auvergne-Rhône-Alpes 26 Drôme 3 19 364 511 553 524 574
28 Normandie 27 Eure 3 23 585 601 843 614 926
24 Centre-Val de Loire 28 Eure-et-Loir 4 15 365 433 233 443 538
53 Bretagne 29 Finistère 4 27 277 909 028 933 992
76 Occitanie 30 Gard 3 23 351 744 178 757 764
76 Occitanie 31 Haute-Garonne 3 27 586 1 362 672 1 385 122
76 Occitanie 32 Gers 3 17 461 191 091 197 953
75 Nouvelle-Aquitaine 33 Gironde 6 33 535 1 583 384 1 607 545
76 Occitanie 34 Hérault 3 25 342 1 144 892 1 162 867
53 Bretagne 35 Ille-et-Vilaine 4 27 333 1 060 199 1 084 554
24 Centre-Val de Loire 36 Indre 4 13 241 222 232 227 999
24 Centre-Val de Loire 37 Indre-et-Loire 3 19 272 606 511 618 820
84 Auvergne-Rhône-Alpes 38 Isère 3 29 512 1 258 722 1 283 384
27 Bourgogne-Franche-Comté 39 Jura 3 17 494 260 188 269 344
75 Nouvelle-Aquitaine 40 Landes 2 15 327 407 444 419 709
24 Centre-Val de Loire 41 Loir-et-Cher 3 15 267 331 915 340 499
84 Auvergne-Rhône-Alpes 42 Loire 3 21 323 762 941 777 328
84 Auvergne-Rhône-Alpes 43 Haute-Loire 3 19 257 227 283 234 190
52 Pays de la Loire 44 Loire-Atlantique 3 31 207 1 394 909 1 423 152
24 Centre-Val de Loire 45 Loiret 3 21 326 678 105 692 540
76 Occitanie 46 Lot 3 17 313 173 828 179 556
75 Nouvelle-Aquitaine 47 Lot-et-Garonne 4 21 319 332 842 341 270
76 Occitanie 48 Lozère 2 13 152 76 601 80 240
52 Pays de la Loire 49 Maine-et-Loire 4 21 177 813 493 833 154
28 Normandie 50 Manche 4 27 446 496 883 512 923
44 Grand Est 51 Marne 4 23 613 568 895 580 671
44 Grand Est 52 Haute-Marne 3 17 426 175 640 180 753
52 Pays de la Loire 53 Mayenne 3 17 242 307 445 316 750
44 Grand Est 54 Meurthe-et-Moselle 4 23 591 733 481 745 300
44 Grand Est 55 Meuse 3 17 499 187 187 192 588
53 Bretagne 56 Morbihan 3 21 250 750 863 771 911
44 Grand Est 57 Moselle 5 27 725 1 043 522 1 062 217
27 Bourgogne-Franche-Comté 58 Nièvre 4 17 309 207 182 212 742
32 Hauts-de-France 59 Nord 6 41 648 2 604 361 2 635 255
32 Hauts-de-France 60 Oise 4 21 679 824 503 841 948
28 Normandie 61 Orne 3 21 385 283 372 291 557
32 Hauts-de-France 62 Pas-de-Calais 7 39 890 1 468 018 1 489 983
84 Auvergne-Rhône-Alpes 63 Puy-de-Dôme 5 31 464 653 742 668 301
75 Nouvelle-Aquitaine 64 Pyrénées-Atlantiques 3 27 546 677 309 695 965
76 Occitanie 65 Hautes-Pyrénées 3 17 469 228 530 234 591
76 Occitanie 66 Pyrénées-Orientales 3 17 226 474 452 482 368
44 Grand Est 67 Bas-Rhin 5 23 514 1 125 559 1 141 511
44 Grand Est 68 Haut-Rhin 4 17 366 764 030 777 917
84 Auvergne-Rhône-Alpes 69 Rhône 2 13 267 1 843 319 1 869 599
27 Bourgogne-Franche-Comté 70 Haute-Saône 2 17 539 236 659 243 264
27 Bourgogne-Franche-Comté 71 Saône-et-Loire 5 29 565 553 595 569 531
52 Pays de la Loire 72 Sarthe 3 21 354 566 506 579 650
84 Auvergne-Rhône-Alpes 73 Savoie 3 19 273 431 174 443 787
84 Auvergne-Rhône-Alpes 74 Haute-Savoie 4 17 279 807 360 828 417
11 Île-de-France 75 Paris 1 1 2 187 526 2 204 773
28 Normandie 76 Seine-Maritime 3 35 708 1 254 378 1 275 559
11 Île-de-France 77 Seine-et-Marne 5 23 507 1 403 997 1 420 469
11 Île-de-France 78 Yvelines 4 21 259 1 438 266 1 463 091
75 Nouvelle-Aquitaine 79 Deux-Sèvres 3 17 256 374 351 384 479
32 Hauts-de-France 80 Somme 4 23 772 572 443 582 464
76 Occitanie 81 Tarn 2 23 314 387 890 398 412
76 Occitanie 82 Tarn-et-Garonne 2 15 195 258 349 264 130
93 Provence-Alpes-Côte d'Azur 83 Var 3 23 153 1 058 740 1 075 653
93 Provence-Alpes-Côte d'Azur 84 Vaucluse 3 17 151 559 479 570 762
52 Pays de la Loire 85 Vendée 3 17 258 675 247 693 455
75 Nouvelle-Aquitaine 86 Vienne 3 19 266 436 876 447 150
75 Nouvelle-Aquitaine 87 Haute-Vienne 3 21 195 374 426 381 379
44 Grand Est 88 Vosges 3 17 507 367 673 378 986
27 Bourgogne-Franche-Comté 89 Yonne 3 21 423 338 291 346 902
27 Bourgogne-Franche-Comté 90 Territoire de Belfort 1 9 101 142 622 145 640
11 Île-de-France 91 Essonne 3 21 194 1 296 130 1 310 599
11 Île-de-France 92 Hauts-de-Seine 3 23 36 1 609 306 1 625 917
11 Île-de-France 93 Seine-Saint-Denis 3 21 40 1 623 111 1 630 133
11 Île-de-France 94 Val-de-Marne 3 25 47 1 387 926 1 397 035
11 Île-de-France 95 Val-d'Oise 3 21 184 1 228 618 1 239 262
01 Guadeloupe 971 Guadeloupe 2 21 32 390 253 396 153
02 Martinique 972 Martinique 4 34 372 594 377 711
03 Guyane 973 Guyane 2 22 268 700 271 124
04 La Réunion 974 La Réunion 4 25 24 853 659 863 063
================================================
FILE: inst/extdata/rules.yaml
================================================
rules:
- expr: speed >= 0
name: 'speed'
label: 'speed positivity'
description: |
speed can not be negative
created: 2020-11-02 11:15:11
meta:
language: validate 0.9.3.36
severity: error
- expr: dist >= 0
name: 'dist'
label: 'distance positivity'
description: |
distance cannot be negative.
created: 2020-11-02 11:15:11
meta:
language: validate 0.9.3.36
severity: error
- expr: speed/dist <= 1.5
name: 'ratio'
label: 'ratio limit'
description: |
The speed to distance ratio can
not exceed 1.5.
created: 2020-11-02 11:15:11
meta:
language: validate 0.9.3.36
severity: error
================================================
FILE: inst/i18n/al.csv
================================================
"label","translation","comment"
"% of the total","% e totalit","Automatically translated"
"% of the total, i.e.","% e totalit, d.m.th.","Automatically translated"
"A shareable link, in that case first sheet will be read","Linku që mund të ndahet, në këtë rast do të lexohet fleta e parë",""
"Add a label to data","Shtoni një etiketë në të dhëna","#TODO #CHECK"
"Add a row","Shtoni një rresht",""
"Apply changes","Apliko ndryshimet",""
"Browse...","Shfletoni...",""
"Cancel","Anulo",""
"Choose a name for the column to be created or modified,","Zgjidhni një emër për kolonën që do të krijohet ose modifikohet,","Automatically translated"
"Choose a number of rows :","Zgjidhni një numër rreshtash:","Automatically translated"
"Choose a percentage :","Zgjidhni një përqindje:","Automatically translated"
"Click on a column name to add it to the expression:","Klikoni në emrin e një kolone për ta shtuar atë në shprehjen:","Automatically translated"
"Click to delete","Klikoni për të fshirë",""
"Click to edit","Klikoni për të redaktuar",""
"Close","Мbyll",""
"Close intervals on the right","Mbyllni intervalet në të djathtë","Automatically translated"
"Column added!","Kolona u shtua!","Automatically translated"
"Convert Numeric to Factor","Konvertoni numerik në faktor","Automatically translated"
"Copy & paste data","Kopjoni dhe ngjisni të dhënat",""
"Copy / Paste","Kopjoni / ngjisni",""
"Count","Numëroni","Automatically translated"
"Create a new column","Krijo një kolonë të re","Automatically translated"
"Create a new variable otherwise replaces the one selected","Krijoni një variabël të ri përndryshe zëvendëson atë të zgjedhur","Automatically translated"
"Create column","Krijo kolonë","Automatically translated"
"Create factor variable","Krijo variabël faktor","Automatically translated"
"Data has %s observations and %s variables.","Të dhënat kanë %s vëzhgime dhe %s variabla",""
"Data ready to be imported!","Të dhënat që janë gati për t'u importuar",""
"Data successfully imported!","Të dhënat u importuan me sukses",""
"Data successfully updated!","Të dhënat janë azhurnuar me sukses!",""
"Data wasn't deleted","Të dhënat nuk u fshinë","Automatically translated"
"Data wasn't updated","Të dhënat nuk u përditësuan","Automatically translated"
"Dataset validation:","Vërtetimi i grupit të të dhënave:","Automatically translated"
"Date format:","Formati i datës:",""
"Date to use as origin to convert date/datetime:","Data që do të përdoret për të konvertuar ndryshoren date/datetime",""
"Decimal separator:","Ndarësi dhjetor:",""
"Delete","Fshije",""
"Do you want to delete the selected row ?","Dëshironi të fshini rreshtin e zgjedhur?",""
"Encoding:","Kodimi:",""
"Enter URL to data:","Futni URL-në e të dhënave:","Automatically translated"
"Enter a shareable link to a GoogleSheet:","Futni një link që mund të ndahet në GoogleSheet:",""
"Enter an expression to define new column:","Futni një shprehje për të përcaktuar kolonën e re:","Automatically translated"
"Environment","Mjedisi",""
"Error","Gabim",""
"External file","Skedari i jashtëm",""
"Factor variable to reorder:","Ndryshorja e faktorit për të rirenditur:","Automatically translated"
"Failed","Dështim",""
"First five rows are shown below:","Pesë rreshtat e parë janë treguar më poshtë:",""
"Googlesheets","Googlesheets",""
"Group calculation by:","Llogaritja e grupit sipas:","Automatically translated"
"Help","Ndihmë",""
"How to import data?","Si të importoni të dhëna?",""
"Import","Importo",""
"Import Google Spreadsheet","Importoni GoogleSheet",""
"Import Url","Importo Url","Automatically translated"
"Import a dataset from an environment","Importoni një grup të dhënash nga mjedisi",""
"Import a file","Importoni skedar",""
"Import data","Importoni të dhënat",""
"Imported data","Të dhëna të importuara","Automatically translated"
"Include lowest value","Përfshi vlerën më të ulët","Automatically translated"
"Information","Informacion",""
"Item has been modified","Artikulli është modifikuar",""
"Levels","Nivelet","Automatically translated"
"List of data.frame...","Lista e tabelave të të dhënave (data.frame)",""
"Max:","Maksimumi:","Automatically translated"
"Mean:","Mesatarja:","Automatically translated"
"Method:","Metoda:","Automatically translated"
"Min:","Min.:","Automatically translated"
"Missing values characters:","Karakteret e vlerave që mungojnë:","Automatically translated"
"Missing:","Mungon:","Automatically translated"
"Most Common:","Më e zakonshme:","Automatically translated"
"New column name cannot be empty","Emri i kolonës së re nuk mund të jetë bosh","Automatically translated"
"New column name:","Emri i kolonës së re:","Automatically translated"
"No","Nr",""
"No data selected!","Nuk ka të dhëna të zgjedhura!",""
"No data to display.","Nuk ka të dhëna për t’u shfaqur.",""
"No data.frame here...","Këtu nuk ka të dhëna (data.frame) ...",""
"No file selected","Nuk është zgjedhur asnjë dokument",""
"No file selected:","Nuk është zgjedhur asnjë dokument:",""
"Not a data.frame","Jo një të dhëna.kornizë","Automatically translated"
"Nothing pasted yet!","Asgjë nuk është ngjitur deri më tani!",""
"Number of breaks:","Numri i pushimeve:","Automatically translated"
"Number of rows:","Numri i rreshtave:",""
"OK","Në rregull",""
"Ooops","Ups",""
"Paste data here:","Ngjitni të dhënat tuaja këtu:",""
"Please copy and paste some data in the dialog box above.","Ju lutemi kopjoni dhe ngjisni disa të dhëna në dritaren e dialogut më poshtë",""
"Please fill in the required fields","Ju lutemi plotësoni fushat e kërkuara",""
"Please paste a valid GoogleSheet link in the dialog box above.","Ju lutemi ngjisni një link të vlefshëm në GoogleSheet në dritaren e dialogut më poshtë.",""
"Please paste a valid link in the dialog box above.","Ju lutemi ngjitni një lidhje të vlefshme në kutinë e dialogut të mësipërm.","Automatically translated"
"Registered","I regjistruar",""
"Required field","Fusha e kërkuar",""
"Row has been saved","Rreshti është ruajtur",""
"Row was not deleted","Rreshti nuk u fshi",""
"Rows to skip before reading data:","Rreshtat për t'u kapërcyer përpara se të lexohen të dhënat:","Automatically translated"
"Sample data by :","Mostra e të dhënave sipas:","Automatically translated"
"Save","Ruaj",""
"Select","Zgjidhni",""
"Select a data.frame:","Zgjidhni data.frame",""
"Select an environment in which to search:","Zgjidhni një mjedis në të cilin do të kërkoni",""
"Select environment","Zgjidhni një mjedis",""
"Select sheet to import:","Zgjidhni një fletë për ta importuar",""
"Some operations are not allowed","Disa operacione nuk lejohen","Automatically translated"
"Something went wrong...","Diçka shkoi keq...",""
"Sort count","Rendit numërimin","Automatically translated"
"The URL that appear in your browser, in that case the current sheet will be read","URL-ja që shfaqet në shfletuesin tuaj, në këtë rast do të lexohet fleta e parë",""
"The row has been deleted","Rreshti është fshirë",""
"The row wasn't added to the data","Rreshti nuk u shtua te të dhënat","Automatically translated"
"URL","URL","Automatically translated"
"Unable to add the row, contact the platform administrator","Rreshti nuk mund të shtohet, kontakto me administratorin e platformës",""
"Unable to delete the row, contact platform administrator","Rreshti nuk mund të fshihet, kontakto me administratorin e platformës",""
"Unable to modify the item, contact the platform administrator","Artikulli nuk mund të modifikohet, kontaktoni administratorin e platformës",""
"Unique values:","Vlerat unike:","Automatically translated"
"Unique:","Unike:","Automatically translated"
"Update","Azhurno",""
"Update & select variables","Azhurnoni dhe zgjidhni variablat",""
"Update factor variable","Përditëso variablin e faktorit","Automatically translated"
"Update levels of a factor","Përditëso nivelet e një faktori","Automatically translated"
"Update row","Përditëso rreshtin",""
"Upload a file:","Bashkangjitni një dokument:",""
"Use a data.frame from your environment or from the environment of a package.","Përdorni data.frame nga mjedisi juaj ose nga mjedisi i paketës",""
"Valid number of columns","Numri i vlefshëm i kolonave","Automatically translated"
"Valid number of rows","Numri i vlefshëm i rreshtave","Automatically translated"
"Validate","Verifiko",""
"Validation:","Verifikimi:",""
"Variable to cut:","Ndryshore për prerje:","Automatically translated"
"View","Shiko",""
"Warning","Paralajmërim","Automatically translated"
"Yes","po",""
"You can either use:","Mund ta përdorni edhe ndonjërën nga këto:",""
"You can import %s files","Mund të importoni dokumente %s",""
"You can import from flat table format supported by","Mund të importoni nga formati i tabelës së sheshtë i mbështetur nga","Automatically translated"
"click to see data","Klikoni këtu për t’i parë të dhënat",""
"data has %s obs. of %s variables.","Të dhënat kanë %vëzhgime dhe %variabla",""
"if several use a comma ',' to separate them","nëse disa përdorin presje ',' për t'i ndarë","Automatically translated"
"lines, i.e.","vijat, d.m.th.","Automatically translated"
"number of rows","numri i rreshtave","Automatically translated"
"proportion of rows","proporcioni i rreshtave","Automatically translated"
"rows","rreshtave","Automatically translated"
"then enter an expression before clicking on the button above to validate or on ","pastaj futni një shprehje përpara se të klikoni në butonin e mësipërm për të vërtetuar ose aktivizuar","Automatically translated"
"to delete it.","për ta fshirë.","Automatically translated"
"Sort by count","Rendit sipas numërimit","Automatically translated"
"Sort by levels","Rendit sipas niveleve","Automatically translated"
================================================
FILE: inst/i18n/cn.csv
================================================
"label","translation","comment"
"% of the total","鍗犳€绘暟鐨�%","Automatically translated"
"% of the total, i.e.","鍗犳€绘暟鐨�%锛屽嵆","Automatically translated"
"A shareable link, in that case first sheet will be read","文件共享链接,我们将导入首个工作簿的数据",""
"Add a label to data","添加数据标签",""
"Add a row","添加一行",""
"Apply changes","应用更改",""
"Browse...","浏览...",""
"Cancel","取消",""
"Choose a name for the column to be created or modified,","涓鸿鍒涘缓鎴栦慨鏀圭殑鍒楅€夋嫨涓€涓悕绉帮紝","Automatically translated"
"Choose a number of rows :","閫夋嫨琛屾暟锛�","Automatically translated"
"Choose a percentage :","閫夋嫨涓€涓櫨鍒嗘瘮锛�","Automatically translated"
"Click on a column name to add it to the expression:","鍗曞嚮鍒楀悕绉板皢鍏舵坊鍔犲埌琛ㄨ揪寮忎腑锛�","Automatically translated"
"Click to delete","点击删除",""
"Click to edit","点击编辑",""
"Close","取消",""
"Close intervals on the right","鍙宠竟闂撮殧寰堣繎","Automatically translated"
"Column added!","涓撴爮宸叉坊鍔狅紒","Automatically translated"
"Convert Numeric to Factor","灏嗘暟瀛楄浆鎹负鍥犲瓙","Automatically translated"
"Copy & paste data","复制粘贴数据",""
"Copy / Paste","复制粘贴",""
"Count","鏁版暟","Automatically translated"
"Create a new column","鍒涘缓涓€涓柊鍒�","Automatically translated"
"Create a new variable otherwise replaces the one selected","鍒涘缓涓€涓柊鍙橀噺锛屽惁鍒欐浛鎹㈡墍閫夊彉閲�","Automatically translated"
"Create column","鍒涘缓涓撴爮","Automatically translated"
"Create factor variable","鍒涘缓鍥犲瓙鍙橀噺","Automatically translated"
"Data has %s observations and %s variables.","数据有 %s 行 %s 列.",""
"Data ready to be imported!","数据等待导入!",""
"Data successfully imported!","数据导入成功!",""
"Data successfully updated!","数据上传成功!",""
"Data wasn't deleted","鏁版嵁娌℃湁琚垹闄�","Automatically translated"
"Data wasn't updated","鏁版嵁鏈洿鏂�","Automatically translated"
"Dataset validation:","鏁版嵁闆嗛獙璇侊細","Automatically translated"
"Date format:","日期格式:",""
"Date to use as origin to convert date/datetime:","日期转换的起始时间:",""
"Decimal separator:","小数点:""""""""""""""""",""
"Delete","删除",""
"Do you want to delete the selected row ?","您要删除选定的行吗?",""
"Encoding:","文件编码:",""
"Enter URL to data:","杈撳叆鏁版嵁鐨� URL锛�","Automatically translated"
"Enter a shareable link to a GoogleSheet:","输入GoogleSheet的共享链接:",""
"Enter an expression to define new column:","杈撳叆琛ㄨ揪寮忔潵瀹氫箟鏂板垪锛�","Automatically translated"
"Environment","环境",""
"Error","错误",""
"External file","外部文件",""
"Factor variable to reorder:","瑕侀噸鏂版帓搴忕殑鍥犲瓙鍙橀噺锛�","Automatically translated"
"Failed","失败",""
"First five rows are shown below:","如下是前5行数据:",""
"Googlesheets","Googlesheets",""
"Group calculation by:","鍒嗙粍璁$畻鏂瑰紡锛�","Automatically translated"
"Help","帮助",""
"How to import data?","如何导入数据?",""
"Import","导入",""
"Import Google Spreadsheet","导入Google数据文件",""
"Import Url","瀵煎叆缃戝潃","Automatically translated"
"Import a dataset from an environment","从环境中导入数据",""
"Import a file","导入文件",""
"Import data","导入数据",""
"Imported data","瀵煎叆鏁版嵁","Automatically translated"
"Include lowest value","鍖呮嫭鏈€浣庡€�","Automatically translated"
"Information","信息",""
"Item has been modified","项目已修改",""
"Levels","绾у埆","Automatically translated"
"List of data.frame...","所有数据文件",""
"Max:","鏈€澶ч檺搴︼細","Automatically translated"
"Mean:","鎰忔€濇槸锛�","Automatically translated"
"Method:","鏂规硶锛�","Automatically translated"
"Min:","鍒嗛挓锛�","Automatically translated"
"Missing values characters:","缂哄け鍊煎瓧绗︼細","Automatically translated"
"Missing:","涓㈠け鐨勶細","Automatically translated"
"Most Common:","鏈€甯歌鐨勶細","Automatically translated"
"New column name cannot be empty","鏂板垪鍚嶄笉鑳戒负绌�","Automatically translated"
"New column name:","鏂板垪鍚嶇О锛�","Automatically translated"
"No","不",""
"No data selected!","未选择数据!",""
"No data to display.","无数据.",""
"No data.frame here...","未检测到数据集...",""
"No file selected","尚未选择文件",""
"No file selected:","尚未选择文件",""
"Not a data.frame","涓嶆槸鏁版嵁妗�","Automatically translated"
"Nothing pasted yet!","尚未粘贴任何数据!",""
"Number of breaks:","浼戞伅娆℃暟锛�","Automatically translated"
"Number of rows:","行数:",""
"OK","OK",""
"Ooops","啊",""
"Paste data here:","粘贴位置:",""
"Please copy and paste some data in the dialog box above.","请在上面的对话框中复制粘贴数据.",""
"Please fill in the required fields","请填写必填字段",""
"Please paste a valid GoogleSheet link in the dialog box above.","链接无效,请核对链接.",""
"Please paste a valid link in the dialog box above.","璇峰湪涓婇潰鐨勫璇濇涓矘璐存湁鏁堢殑閾炬帴銆�","Automatically translated"
"Registered","挂号的",""
"Required field","必填项目",""
"Row has been saved","行已保存”",""
"Row was not deleted","行未删除",""
"Rows to skip before reading data:","璇诲彇鏁版嵁涔嬪墠瑕佽烦杩囩殑琛岋細","Automatically translated"
"Sample data by :","鏍锋湰鏁版嵁锛�","Automatically translated"
"Save","节省",""
"Select","选择",""
"Select a data.frame:","选择数据文件:",""
"Select an environment in which to search:","选择搜索环境:",""
"Select environment","选择环境",""
"Select sheet to import:","选择工作簿:",""
"Some operations are not allowed","鏈変簺鎿嶄綔鏄笉鍏佽鐨�","Automatically translated"
"Something went wrong...","出错了...",""
"Sort count","鎺掑簭璁℃暟","Automatically translated"
"The URL that appear in your browser, in that case the current sheet will be read","浏览器复制链接,我们将导入当前工作簿的数据",""
"The row has been deleted","该行已被删除",""
"The row wasn't added to the data","璇ヨ鏈坊鍔犲埌鏁版嵁涓�","Automatically translated"
"URL","缃戝潃","Automatically translated"
"Unable to add the row, contact the platform administrator","无法添加行,联系平台管理员",""
"Unable to delete the row, contact platform administrator","无法删除行,联系平台管理员",""
"Unable to modify the item, contact the platform administrator","无法修改物品,联系平台管理员",""
"Unique values:","鐙壒鐨勪环鍊艰锛�","Automatically translated"
"Unique:","鐙壒鐨勶細","Automatically translated"
"Update","更新",""
"Update & select variables","选择并更新数据",""
"Update factor variable","鏇存柊鍥犲瓙鍙橀噺","Automatically translated"
"Update levels of a factor","鏇存柊鍥犲瓙鐨勬按骞�","Automatically translated"
"Update row","更新行",""
"Upload a file:","上传文件:",""
"Use a data.frame from your environment or from the environment of a package.","使用工作环境中或R包中数据集.",""
"Valid number of columns","鏈夋晥鍒楁暟","Automatically translated"
"Valid number of rows","鏈夋晥琛屾暟","Automatically translated"
"Validate","验证",""
"Validation:","验证:",""
"Variable to cut:","瑕佸壀鍒囩殑鍙橀噺锛�","Automatically translated"
"View","预览",""
"Warning","璀﹀憡","Automatically translated"
"Yes","是的",""
"You can either use:","你还可以使用:",""
"You can import %s files","你可以上传 %s 个文件",""
"You can import from flat table format supported by","鎮ㄥ彲浠ヤ粠鏀寔鐨勫钩闈㈣〃鏍兼牸寮忓鍏�","Automatically translated"
"click to see data","数据预览",""
"data has %s obs. of %s variables.","数据有 %s 行 %s 列.",""
"if several use a comma ',' to separate them","濡傛灉澶氫釜浣跨敤閫楀彿鈥�,鈥濆垎闅�","Automatically translated"
"lines, i.e.","绾匡紝鍗�","Automatically translated"
"number of rows","琛屾暟","Automatically translated"
"proportion of rows","琛岀殑姣斾緥","Automatically translated"
"rows","琛�","Automatically translated"
"then enter an expression before clicking on the button above to validate or on ","鐒跺悗杈撳叆涓€涓〃杈惧紡锛岀劧鍚庡崟鍑讳笂闈㈢殑鎸夐挳杩涜楠岃瘉鎴�","Automatically translated"
"to delete it.","鍒犻櫎瀹冦€�","Automatically translated"
"Sort by count","鎸夋暟閲忔帓搴�","Automatically translated"
"Sort by levels","鎸夌骇鍒帓搴�","Automatically translated"
================================================
FILE: inst/i18n/de.csv
================================================
"label","translation","comment"
"% of the total","% von allen","Automatically translated"
"% of the total, i.e.","% der Gesamtmenge, d.h.","Automatically translated"
"A shareable link, in that case first sheet will be read","Ein teilbarer Link, in diesem Fall wird das erste Arbeitsblatt eingelesen",""
"Add a label to data","Bezeichnung zu Daten hinzufügen",""
"Add a row","Fügen Sie eine Zeile hinzu",""
"Apply changes","Änderungen übernehmen",""
"Browse...","Durchsuchen...",""
"Cancel","Absagen",""
"Choose a name for the column to be created or modified,","Wählen Sie einen Namen für die Spalte, die erstellt oder geändert werden soll.","Automatically translated"
"Choose a number of rows :","Wählen Sie eine Anzahl von Zeilen:","Automatically translated"
"Choose a percentage :","Wählen Sie einen Prozentsatz:","Automatically translated"
"Click on a column name to add it to the expression:","Klicken Sie auf einen Spaltennamen, um ihn dem Ausdruck hinzuzufügen:","Automatically translated"
"Click to delete","Zum Löschen klicken",""
"Click to edit","Zum Bearbeiten anklicken",""
"Close","Schließen",""
"Close intervals on the right","Schließen Sie die Intervalle rechts","Automatically translated"
"Column added!","Spalte hinzugefügt!","Automatically translated"
"Convert Numeric to Factor","Numerisch in Faktor umwandeln","Automatically translated"
"Copy & paste data","Daten hier Kopieren und Einfügen",""
"Copy / Paste","Kopieren / Einfügen",""
"Count","Zählen","Automatically translated"
"Create a new column","Erstellen Sie eine neue Spalte","Automatically translated"
"Create a new variable otherwise replaces the one selected","Erstellen Sie eine neue Variable, andernfalls ersetzt sie die ausgewählte","Automatically translated"
"Create column","Spalte erstellen","Automatically translated"
"Create factor variable","Faktorvariable erstellen","Automatically translated"
"Data has %s observations and %s variables.","Daten haben %s Einträge und %s Variablen.",""
"Data ready to be imported!","Daten bereit zum Import",""
"Data successfully imported!","Daten erfolgreich importiert!",""
"Data successfully updated!","Daten Aktualisierung erfolgreich !",""
"Data wasn't deleted","Daten wurden nicht gelöscht","Automatically translated"
"Data wasn't updated","Daten wurden nicht aktualisiert","Automatically translated"
"Dataset validation:","Datensatzvalidierung:","Automatically translated"
"Date format:","Datumsformat :",""
"Date to use as origin to convert date/datetime:","Ursprungsdatum zur Umwandlung von Datum/Datum-Zeit :",""
"Decimal separator:","Dezimaltrennzeichen:",""
"Delete","Löschen",""
"Do you want to delete the selected row ?","Möchten Sie die ausgewählte Zeile löschen?",""
"Encoding:","Codierung:",""
"Enter URL to data:","Geben Sie die URL zu den Daten ein:","Automatically translated"
"Enter a shareable link to a GoogleSheet:","Teilbaren GoogleSheet Link eingeben:",""
"Enter an expression to define new column:","Geben Sie einen Ausdruck ein, um eine neue Spalte zu definieren:","Automatically translated"
"Environment","Umgebung",""
"Error","Fehler",""
"External file","Externe Datei",""
"Factor variable to reorder:","Neu anzuordnende Faktorvariable:","Automatically translated"
"Failed","Fehlgeschlagen",""
"First five rows are shown below:","Die ersten fünf Reihen werden unten angezeigt:",""
"Googlesheets","Googlesheets",""
"Group calculation by:","Gruppenberechnung nach:","Automatically translated"
"Help","Hilfe",""
"How to import data?","Wie sollen Daten importiert werden ?",""
"Import","Importieren",""
"Import Google Spreadsheet","GoogleSheet importieren",""
"Import Url","URL importieren","Automatically translated"
"Import a dataset from an environment","Importieren Sie ein Datenset aus einer Umgebung",""
"Import a file","Datei importieren",""
"Import data","Daten importieren",""
"Imported data","Importierte Daten","Automatically translated"
"Include lowest value","Geben Sie den niedrigsten Wert an","Automatically translated"
"Information","Information",""
"Item has been modified","Artikel wurde geändert",""
"Levels","Ebenen","Automatically translated"
"List of data.frame...","Liste der Daten-Tabellen",""
"Max:","Maximal:","Automatically translated"
"Mean:","Bedeuten:","Automatically translated"
"Method:","Methode:","Automatically translated"
"Min:","Mindest:","Automatically translated"
"Missing values characters:","Fehlende Wertezeichen:","Automatically translated"
"Missing:","Fehlen:","Automatically translated"
"Most Common:","Am gebräuchlichsten:","Automatically translated"
"New column name cannot be empty","Der neue Spaltenname darf nicht leer sein","Automatically translated"
"New column name:","Neuer Spaltenname:","Automatically translated"
"No","Nein",""
"No data selected!","Keine Daten ausgewählt!",""
"No data to display.","Keine Daten zum Anzeigen.",""
"No data.frame here...","Keine Daten-Tabellen hier...",""
"No file selected","Keine Datei ausgewählt",""
"No file selected:","Keine Datei ausgewählt",""
"Not a data.frame","Kein Datenrahmen","Automatically translated"
"Nothing pasted yet!","Noch nichts eingefügt!",""
"Number of breaks:","Anzahl Pausen:","Automatically translated"
"Number of rows:","Anzahl Reihen :",""
"OK","OK",""
"Ooops","Ooops",""
"Paste data here:","Daten hier einfügen:",""
"Please copy and paste some data in the dialog box above.","Bitte Daten in obige Dialog-Box Kopieren und Einfügen.",""
"Please fill in the required fields","Bitte füllen Sie die erforderlichen Felder aus",""
"Please paste a valid GoogleSheet link in the dialog box above.","Bitte gültigen GoogleSheet Link in die Dialog-Box oben einfügen .",""
"Please paste a valid link in the dialog box above.","Bitte fügen Sie einen gültigen Link in das Dialogfeld oben ein.","Automatically translated"
"Registered","Eingetragen",""
"Required field","Pflichtfeld",""
"Row has been saved","Zeile wurde gespeichert",""
"Row was not deleted","Zeile wurde nicht gelöscht",""
"Rows to skip before reading data:","Vor dem Lesen der Daten zu überspringende Zeilen:","Automatically translated"
"Sample data by :","Beispieldaten von:","Automatically translated"
"Save","Speichern",""
"Select","Auswählen",""
"Select a data.frame:","Daten-Tabelle auswählen:",""
"Select an environment in which to search:","Wählen Sie eine Umgebung aus, in der gesucht werden soll:",""
"Select environment","Umgebung auswählen",""
"Select sheet to import:","Arbeitsblatt zum Importieren auswählen:",""
"Some operations are not allowed","Einige Vorgänge sind nicht zulässig","Automatically translated"
"Something went wrong...","Etwas ist schief gelaufen...",""
"Sort count","Anzahl sortieren","Automatically translated"
"The URL that appear in your browser, in that case the current sheet will be read","Die URL die im Browser aufscheint, in diesem Fall wird das aktuielle Arbeitsblatt eingelesen",""
"The row has been deleted","Die Zeile wurde gelöscht",""
"The row wasn't added to the data","Die Zeile wurde nicht zu den Daten hinzugefügt","Automatically translated"
"URL","URL","Automatically translated"
"Unable to add the row, contact the platform administrator","Die Zeile kann nicht hinzugefügt werden. Wenden Sie sich an den Plattformadministrator",""
"Unable to delete the row, contact platform administrator","Die Zeile kann nicht gelöscht werden. Wenden Sie sich an den Plattformadministrator",""
"Unable to modify the item, contact the platform administrator","Das Element kann nicht geändert werden. Wenden Sie sich an den Plattformadministrator",""
"Unique values:","Einzigartige Werte:","Automatically translated"
"Unique:","Einzigartig:","Automatically translated"
"Update","Aktualisieren",""
"Update & select variables","Variablen aktualisieren & auswählen",""
"Update factor variable","Faktorvariable aktualisieren","Automatically translated"
"Update levels of a factor","Aktualisieren Sie die Ebenen eines Faktors","Automatically translated"
"Update row","Zeile aktualisieren",""
"Upload a file:","Datei hochladen :",""
"Use a data.frame from your environment or from the environment of a package.","Benutze eine Daten-Tabelle aus der eigenen Umgebung oder der Umgebung eines Pakets.",""
"Valid number of columns","Gültige Anzahl von Spalten","Automatically translated"
"Valid number of rows","Gültige Anzahl von Zeilen","Automatically translated"
"Validate","Validieren",""
"Validation:","Validierung :",""
"Variable to cut:","Variable zum Schneiden:","Automatically translated"
"View","Ansehen",""
"Warning","Warnung","Automatically translated"
"Yes","Ja",""
"You can either use:","Sie können entweder verwenden :",""
"You can import %s files","Sie können %s Datein importieren",""
"You can import from flat table format supported by","Sie können aus dem von unterstützten Flat-Table-Format importieren","Automatically translated"
"click to see data","klicken, um Daten anzuzeigen",""
"data has %s obs. of %s variables.","Daten haben %s Einträge und %s Variablen.",""
"if several use a comma ',' to separate them","Bei mehreren verwenden Sie zur Trennung ein Komma „,“.","Automatically translated"
"lines, i.e.","Linien, d.h.","Automatically translated"
"number of rows","Anzahl der Reihen","Automatically translated"
"proportion of rows","Anteil der Reihen","Automatically translated"
"rows","Reihen","Automatically translated"
"then enter an expression before clicking on the button above to validate or on ","Geben Sie dann einen Ausdruck ein, bevor Sie zum Bestätigen oder Einschalten auf die Schaltfläche oben klicken","Automatically translated"
"to delete it.","um es zu löschen.","Automatically translated"
"Sort by count","Nach Anzahl sortieren","Automatically translated"
"Sort by levels","Nach Ebenen sortieren","Automatically translated"
================================================
FILE: inst/i18n/es.csv
================================================
"label","translation","comment"
"% of the total","% del total","Automatically translated"
"% of the total, i.e.","% del total, es decir","Automatically translated"
"A shareable link, in that case first sheet will be read","Un enlace compartible, en ese caso, primera hoja se leerá",""
"Add a label to data","Añadir una etiqueta a los datos",""
"Add a row","Agregar una fila",""
"Apply changes","Aplicar cambios",""
"Browse...","Explorar...",""
"Cancel","Cancelar",""
"Choose a name for the column to be created or modified,","Elija un nombre para la columna que se creará o modificará,","Automatically translated"
"Choose a number of rows :","Elija una cantidad de filas:","Automatically translated"
"Choose a percentage :","Elige un porcentaje:","Automatically translated"
"Click on a column name to add it to the expression:","Haga clic en el nombre de una columna para agregarla a la expresión:","Automatically translated"
"Click to delete","Haga clic para eliminar",""
"Click to edit","Haz click para editar",""
"Close","Cerrar",""
"Close intervals on the right","Cerrar intervalos a la derecha","Automatically translated"
"Column added!","¡Columna agregada!","Automatically translated"
"Convert Numeric to Factor","Convertir numérico a factor","Automatically translated"
"Copy & paste data","Copiar y pegar datos","Automatically translated"
"Copy / Paste","Copiar / Pegar",""
"Count","Contar","Automatically translated"
"Create a new column","Crear una nueva columna","Automatically translated"
"Create a new variable otherwise replaces the one selected","Crea una nueva variable, de lo contrario reemplaza la seleccionada","Automatically translated"
"Create column","Crear columna","Automatically translated"
"Create factor variable","Crear variable de factor","Automatically translated"
"Data has %s observations and %s variables.","Los datos tienen %s obs. de %s variables.",""
"Data ready to be imported!","¡Datos listos para ser importados!","Automatically translated"
"Data successfully imported!","Datos importados con éxito!",""
"Data successfully updated!","Datos actualizados con éxito!",""
"Data wasn't deleted","Los datos no fueron eliminados","Automatically translated"
"Data wasn't updated","Los datos no fueron actualizados.","Automatically translated"
"Dataset validation:","Validación del conjunto de datos:","Automatically translated"
"Date format:","Formato de fecha :",""
"Date to use as origin to convert date/datetime:","Fecha a usar como origen para convertir fecha/datetime :",""
"Decimal separator:","Separador decimal :",""
"Delete","Borrar",""
"Do you want to delete the selected row ?","¿Desea eliminar la fila seleccionada?",""
"Encoding:","Codificación :",""
"Enter URL to data:","Ingrese la URL a los datos:","Automatically translated"
"Enter a shareable link to a GoogleSheet:","Introduzca un enlace compartible a un archivo de GoogleSheet:",""
"Enter an expression to define new column:","Ingrese una expresión para definir una nueva columna:","Automatically translated"
"Environment","Entorno",""
"Error","Error",""
"External file","Archivo externo",""
"Factor variable to reorder:","Variable factorial a reordenar:","Automatically translated"
"Failed","Falló",""
"First five rows are shown below:","Las cinco primeras filas se muestran a continuación:",""
"Googlesheets","Archivos de GoogleSheet",""
"Group calculation by:","Cálculo de grupo por:","Automatically translated"
"Help","Ayuda",""
"How to import data?","¿Cómo importar datos?",""
"Import","Importar",""
"Import Google Spreadsheet","Importar hoja de cálculo de Google","Automatically translated"
"Import Url","Importar URL","Automatically translated"
"Import a dataset from an environment","Importar un conjunto de datos desde un entorno","Automatically translated"
"Import a file","Importar un archivo","Automatically translated"
"Import data","Importar datos",""
"Imported data","Datos importados","Automatically translated"
"Include lowest value","Incluir el valor más bajo","Automatically translated"
"Information","Información",""
"Item has been modified","El artículo ha sido modificado",""
"Levels","Niveles","Automatically translated"
"List of data.frame...","Lista de data.frame...",""
"List of data.frame...","Lista de data.frame...",""
"Max:","Máximo:","Automatically translated"
"Mean:","Significar:","Automatically translated"
"Method:","Método:","Automatically translated"
"Min:","Mínimo:","Automatically translated"
"Missing values characters:","Caracteres de valores faltantes:","Automatically translated"
"Missing:","Desaparecido:","Automatically translated"
"Most Common:","Más común:","Automatically translated"
"New column name cannot be empty","El nombre de la nueva columna no puede estar vacío","Automatically translated"
"New column name:","Nuevo nombre de columna:","Automatically translated"
"No","No",""
"No","No",""
"No data selected!","No hay datos seleccionados!",""
"No data to display.","No hay datos para mostrar.",""
"No data.frame here...","No hay data.frame aquí...",""
"No file selected","No hay archivo seleccionado",""
"No file selected:","No hay archivo seleccionado :",""
"Not a data.frame","No es un marco de datos","Automatically translated"
"Nothing pasted yet!","Aún no se ha pegado nada!",""
"Number of breaks:","Número de descansos:","Automatically translated"
"Number of rows:","Número de filas :",""
"OK","Aceptar",""
"Ooops","Ups",""
"Paste data here:","Pegar datos aquí :",""
"Please copy and paste some data in the dialog box above.","Por favor, copie y pegue algún dato en la caja de diálogo anterior.",""
"Please fill in the required fields","Por favor llene los campos requeridos",""
"Please paste a valid GoogleSheet link in the dialog box above.","Por favor, pegue un enlace válido a un archivo de GoogleSheet en la caja de diálogo anterior.",""
"Please paste a valid link in the dialog box above.","Pegue un enlace válido en el cuadro de diálogo de arriba.","Automatically translated"
"Registered","Registrado",""
"Required field","Campo requerido",""
"Row has been saved","Se ha guardado la fila",""
"Row was not deleted","La fila no fue eliminada",""
"Rows to skip before reading data:","Filas que se deben omitir antes de leer los datos:","Automatically translated"
"Sample data by :","Datos de muestra por:","Automatically translated"
"Save","Ahorrar",""
"Select","Seleccione",""
"Select a data.frame:","Seleccionar un data.frame :",""
"Select an environment in which to search:","Seleccionar un entorno en el que buscar :",""
"Select environment","Seleccionar entorno",""
"Select sheet to import:","Seleccionar hoja para importar :",""
"Some operations are not allowed","Algunas operaciones no están permitidas.","Automatically translated"
"Something went wrong...","Algo salió mal...",""
"Sort count","Ordenar recuento","Automatically translated"
"The URL that appear in your browser, in that case the current sheet will be read","La URL que aparece en su navegador, en ese caso, la hoja actual se leerá",""
"The row has been deleted","La fila ha sido eliminada",""
"The row wasn't added to the data","La fila no se agregó a los datos.","Automatically translated"
"URL","URL","Automatically translated"
"Unable to add the row, contact the platform administrator","No se puede agregar la fila, comuníquese con el administrador de la plataforma",""
"Unable to delete the row, contact platform administrator","No se puede eliminar la fila, comuníquese con el administrador de la plataforma",""
"Unable to modify the item, contact the platform administrator","No se puede modificar el elemento, comuníquese con el administrador de la plataforma",""
"Unique values:","Valores únicos:","Automatically translated"
"Unique:","Único:","Automatically translated"
"Update","Actualizar",""
"Update & select variables","Actualizar y seleccionar variables","Automatically translated"
"Update factor variable","Variable de factor de actualización","Automatically translated"
"Update levels of a factor","Actualizar niveles de un factor","Automatically translated"
"Update row","Actualizar fila",""
"Upload a file:","Subir un archivo :",""
"Use a data.frame from your environment or from the environment of a package.","Usar un data.frame de su entorno o del entorno de un paquete.",""
"Valid number of columns","Número válido de columnas","Automatically translated"
"Valid number of rows","Número válido de filas","Automatically translated"
"Validate","Validar",""
"Validation:","Validación:","Automatically translated"
"Variable to cut:","Variable a cortar:","Automatically translated"
"View","Visualizar",""
"Warning","Advertencia","Automatically translated"
"Yes","Sí",""
"Yes","Sí",""
"You can either use:","Puede usar:",""
"You can import %s files","Puede importar %s archivos",""
"You can import from flat table format supported by","Puede importar desde el formato de tabla plana compatible con","Automatically translated"
"click to see data","click para ver datos","Automatically translated"
"data has %s obs. of %s variables.","Los datos tienen %s obs. de %s variables.",""
"if several use a comma ',' to separate them","si son varios use una coma ',' para separarlos","Automatically translated"
"lines, i.e.","líneas, es decir","Automatically translated"
"number of rows","número de filas","Automatically translated"
"proportion of rows","proporción de filas","Automatically translated"
"rows","filas","Automatically translated"
"then enter an expression before clicking on the button above to validate or on ","luego ingrese una expresión antes de hacer clic en el botón de arriba para validar o en","Automatically translated"
"to delete it.","para borrarlo.","Automatically translated"
"Sort by count","Ordenar por conteo","Automatically translated"
"Sort by levels","Ordenar por niveles","Automatically translated"
================================================
FILE: inst/i18n/extract_labels.R
================================================
#' Function to extract labels
#'
#' @param folder file directory
#'
#' @return an extraction of the labels contained in the directory files
#' @importFrom stringr str_subset str_extract_all str_remove_all
#' @export
#'
#' @examples extract_labels(folder = "R")
extract_labels <- function(folder = "R") {
files <- list.files(folder)
list_extractions <- lapply(
X = files,
FUN = function(file) {
read_file <- readLines(file.path(folder, file))
extraction <- str_extract_all(
string = str_subset(read_file, "i18n"),
pattern = 'i18n\\(".*?"\\)'
) |>
unlist()
extraction
}
)
extract_labels <- unlist(list_extractions, recursive = TRUE)
str_remove_all(unique(extract_labels), paste(c("i18n", "\"", "\\)", "\\("), collapse = "|"))
}
#' Update all csvs that are in inst/i18n
#'
#' @param labels results of label extractions
#' @param lang the language that you want to translate the text into. See polyglotr::google_supported_languages for the Table with the codes of available languages
#' @param lang_csv the name of the csv file
#' @param translation TRUE or FALSE if you want to translate the language
#' @param ... other arguments passed to datamods::translate_labels
#'
#' @return all csvs updated
#' @importFrom data.table merge fwrite data.table fread unique
#' @export
#'
#' @examples update_csv(labels = extract_labels(folder = "R"))
#' new_csv_fr <- fread("inst/i18n/fr.csv")
update_csv <- function(labels,
lang,
lang_csv,
translation = TRUE,
...) {
old <- fread(file = sprintf("inst/i18n/%s.csv", lang_csv), encoding = "UTF-8", fill = TRUE)
new <- merge(
x = data.table(label = unique(labels)),
y = old,
by = "label",
all.x = TRUE
)
if (isTRUE(translation)) {
final <- rbind(
new[!is.na(translation)],
translate_labels(labels = new[is.na(translation)]$label, target_language = lang, ...),
fill = TRUE
)
} else {
final <- new
}
fwrite(final, file = sprintf("inst/i18n/%s.csv", lang_csv), row.names = FALSE, na = '', quote = TRUE)
}
#' Translate labels
#'
#' @param labels labels to translate
#' @param source_language the language that you want to translate the text into. See polyglotr::google_supported_languages for the Table with the codes of available languages
#' @param target_language the language of the text that you want to translate. See polyglotr::google_supported_languages for the Table with the codes of available languages
#' @param encoding Name of encoding. See stringi::stri_enc_list() for a complete list
#'
#' @importFrom polyglotr google_translate
#' @importFrom stringr str_conv
#' @importFrom data.table data.table
#'
#' @return a data frame with translated labels
#' @export
#'
#' @examples translate_labels(labels = extract_labels(folder = "R"))
translate_labels <- function(labels,
source_language = "en",
target_language = "fr",
encoding = "UTF-8") {
translation <- polyglotr::google_translate(
text = labels,
target_language = target_language,
source_language = source_language
)
data.table(
label = labels,
translation = translation |>
unlist() |>
str_conv(encoding),
comment = "Automatically translated"
)
}
================================================
FILE: inst/i18n/fr.csv
================================================
"label","translation","comment"
"% of the total","% du total","Automatically translated"
"% of the total, i.e.","% du total, soit","Automatically translated"
"A shareable link, in that case first sheet will be read","Un lien partageable, dans ce cas la première feuille sera lue",""
"Add a label to data","Ajouter un libellé aux données",""
"Add a row","Ajouter",""
"Apply changes","Appliquer les changements",""
"Browse...","Parcourir...",""
"Cancel","Annuler",""
"Choose a name for the column to be created or modified,","Choisissez un nom pour la colonne à créer ou à modifier,","Automatically translated"
"Choose a number of rows :","Choisissez un nombre de lignes :","Automatically translated"
"Choose a percentage :","Choisissez un pourcentage :","Automatically translated"
"Click on a column name to add it to the expression:","Cliquez sur un nom de colonne pour l'ajouter à l'expression :","Automatically translated"
"Click to delete","Cliquez pour supprimer",""
"Click to edit","Cliquez pour modifier",""
"Close","Fermer",""
"Close intervals on the right","Intervalles rapprochés à droite","Automatically translated"
"Column added!","Colonne ajoutée !","Automatically translated"
"Convert Numeric to Factor","Convertir un numérique en facteur","Automatically translated"
"Copy & paste data","Copier / coller des données",""
"Copy / Paste","Copier / Coller",""
"Count","Compter","Automatically translated"
"Create a new column","Créer une nouvelle colonne","Automatically translated"
"Create a new variable otherwise replaces the one selected","Créer une nouvelle variable sinon remplace celle sélectionnée","Automatically translated"
"Create column","Créer une colonne","Automatically translated"
"Create factor variable","Créer une variable de facteur","Automatically translated"
"Data has %s observations and %s variables.","Les données ont %s observations et %s variables.",""
"Data ready to be imported!","Données prêtes à être importées",""
"Data successfully imported!","Données importées avec succès",""
"Data successfully updated!","Données mises à jour avec succès !",""
"Data wasn't deleted","Les données n'ont pas été supprimées","Automatically translated"
"Data wasn't updated","Les données n'ont pas été mises à jour","Automatically translated"
"Dataset validation:","Validation de l'ensemble de données :","Automatically translated"
"Date format:","Format des dates :",""
"Date to use as origin to convert date/datetime:","Date à utiliser comme origine pour convertir des dates au format numérique :",""
"Decimal separator:","Séparateur de décimal :",""
"Delete","Effacer",""
"Do you want to delete the selected row ?","Voulez-vous supprimer la ligne sélectionnée ?",""
"Encoding:","Encodage :",""
"Enter URL to data:","Entrez l'URL des données :","Automatically translated"
"Enter a shareable link to a GoogleSheet:","Entrez un lien partageable vers une GoogleSheet :",""
"Enter an expression to define new column:","Entrez une expression pour définir une nouvelle colonne :","Automatically translated"
"Environment","Environnement",""
"Error","Erreur",""
"External file","Fichier",""
"Factor variable to reorder:","Variable de facteur à réorganiser :","Automatically translated"
"Failed","Echec",""
"First five rows are shown below:","Les cinq premières lignes sont affichées ci-dessous :",""
"Googlesheets","Googlesheets",""
"Group calculation by:","Calcul de groupe par :","Automatically translated"
"Help","Aide",""
"How to import data?","Comment importer des données ?",""
"Import","Import",""
"Import Google Spreadsheet","Importer une GoogleSheet",""
"Import Url","URL d'importation","Automatically translated"
"Import a dataset from an environment","Importer un jeu de données depuis l'environnement global",""
"Import a file","Import d'un fichier",""
"Import data","Importer les données",""
"Imported data","Données importées","Automatically translated"
"Include lowest value","Inclure la valeur la plus basse","Automatically translated"
"Information","Informations",""
"Item has been modified","L'élément a été modifié",""
"Levels","Les niveaux","Automatically translated"
"List of data.frame...","Liste des tableau de données",""
"Max:","Maximale :","Automatically translated"
"Mean:","Signifier:","Automatically translated"
"Method:","Méthode:","Automatically translated"
"Min:","Min :","Automatically translated"
"Missing values characters:","Caractères de valeurs manquants :","Automatically translated"
"Missing:","Manquant:","Automatically translated"
"Most Common:","Le plus commun:","Automatically translated"
"New column name cannot be empty","Le nom de la nouvelle colonne ne peut pas être vide","Automatically translated"
"New column name:","Nouveau nom de colonne :","Automatically translated"
"No","Non",""
"No data selected!","Pas de données sélectionnées",""
"No data to display.","Pas de données à afficher.",""
"No data.frame here...","Pas de données ici...",""
"No file selected","Pas de fichier sélectionné",""
"No file selected:","Aucun fichier sélectionné",""
"Not a data.frame","Pas un data.frame","Automatically translated"
"Nothing pasted yet!","Rien n'a encore été collé !",""
"Number of breaks:","Nombre de pauses :","Automatically translated"
"Number of rows:","Nombre de lignes :",""
"OK","OK",""
"Ooops","Ooops",""
"Paste data here:","Collez vos données ici :",""
"Please copy and paste some data in the dialog box above.","Veuillez copier et coller certaines données dans la boîte de dialogue ci-dessus.",""
"Please fill in the required fields","Merci de remplir les champs obligatoires",""
"Please paste a valid GoogleSheet link in the dialog box above.","Veuillez coller un lien GoogleSheet valide dans la boîte de dialogue ci-dessus.",""
"Please paste a valid link in the dialog box above.","Veuillez coller un lien valide dans la boîte de dialogue ci-dessus.","Automatically translated"
"Registered","Enregistré",""
"Required field","Champs requis",""
"Row has been saved","La ligne a été enregistrée",""
"Row was not deleted","La ligne n'a pas été supprimée",""
"Rows to skip before reading data:","Lignes à ignorer avant de lire les données :","Automatically translated"
"Sample data by :","Echantillonner les données selon :",""
"Save","Enregistrer",""
"Select","Sélectionner",""
"Select a data.frame:","Sélectionner un data.frame :",""
"Select an environment in which to search:","Sélectionner un environnement dans lequel rechercher :",""
"Select environment","Sélectionner un environnement",""
"Select sheet to import:","Sélectionner la feuille à importer :",""
"Some operations are not allowed","Certaines opérations ne sont pas autorisées","Automatically translated"
"Something went wrong...","Un problème est survenu...",""
"Sort count","Nombre de tris","Automatically translated"
"The URL that appear in your browser, in that case the current sheet will be read","L'URL qui apparaît dans votre navigateur, dans ce cas la feuille active sera lue",""
"The row has been deleted","La ligne a été supprimée",""
"The row wasn't added to the data","La ligne n'a pas été ajoutée aux données","Automatically translated"
"URL","URL",""
"Unable to add the row, contact the platform administrator","Impossible d'ajouter la ligne, contactez l'administrateur de la plateforme",""
"Unable to delete the row, contact platform administrator","Impossible de supprimer la ligne, contactez l'administrateur de la plateforme",""
"Unable to modify the item, contact the platform administrator","Impossible de modifier l'élément, contactez l'administrateur de la plateforme",""
"Unique values:","Valeurs uniques :","Automatically translated"
"Unique:","Unique:","Automatically translated"
"Update","Modifier",""
"Update & select variables","Modifier et sélectionner des variables",""
"Update factor variable","Variable de facteur de mise à jour","Automatically translated"
"Update levels of a factor","Mettre à jour les niveaux d'un facteur","Automatically translated"
"Update row","Mettre à jour la ligne",""
"Upload a file:","Charger un fichier :",""
"Use a data.frame from your environment or from the environment of a package.","Utiliser un tableau de données de votre environnement ou de celui d'un paquet.",""
"Valid number of columns","Nombre de colonnes valide","Automatically translated"
"Valid number of rows","Nombre de lignes valide","Automatically translated"
"Validate","Validation",""
"Validation:","Validation :",""
"Variable to cut:","Variable à couper :","Automatically translated"
"View","Affichage",""
"Warning","Avertissement","Automatically translated"
"Yes","Oui",""
"You can either use:","Vous pouvez utiliser au choix :",""
"You can import %s files","Vous pouvez importer des fichers %s",""
"You can import from flat table format supported by","Vous pouvez importer à partir du format de tableau plat pris en charge par","Automatically translated"
"click to see data","cliquez pour afficher les données",""
"data has %s obs. of %s variables.","les données ont %s observations et %s colonnes.",""
"if several use a comma ',' to separate them","si plusieurs utilisent une virgule ',' pour les séparer","Automatically translated"
"lines, i.e.","lignes, c'est-à-dire","Automatically translated"
"number of rows","Nombre de lignes",""
"proportion of rows","Proportion de lignes",""
"rows","lignes","Automatically translated"
"then enter an expression before clicking on the button above to validate or on ","puis saisissez une expression avant de cliquer sur le bouton ci-dessus pour valider ou sur","Automatically translated"
"to delete it.","pour le supprimer.","Automatically translated"
"Sort by count","Trier par nombre","Automatically translated"
"Sort by levels","Trier par niveaux","Automatically translated"
================================================
FILE: inst/i18n/it.csv
================================================
"label","translation","comment"
"% of the total","% del totale","Automatically translated"
"% of the total, i.e.","% del totale, cioè","Automatically translated"
"A shareable link, in that case first sheet will be read","Un link condivisibile, in questo caso sarà letta la prima scheda",""
"Add a label to data","Aggiungi un'etichetta ai dati",""
"Add a row","Aggiungi una riga",""
"Apply changes","Applica le modifiche",""
"Browse...","Sfoglia...",""
"Cancel","Annulla",""
"Choose a name for the column to be created or modified,","Scegli un nome per la colonna da creare o modificare,","Automatically translated"
"Choose a number of rows :","Scegli un numero di righe:","Automatically translated"
"Choose a percentage :","Scegli una percentuale:","Automatically translated"
"Click on a column name to add it to the expression:","Clicca sul nome di una colonna per aggiungerla all'espressione:","Automatically translated"
"Click to delete","Clicca per eliminare",""
"Click to edit","Clicca per modificare",""
"Close","Chiudi",""
"Close intervals on the right","Intervalli chiusi a destra","Automatically translated"
"Column added!","Colonna aggiunta","Automatically translated"
"Convert Numeric to Factor","Coverti una variabile numerica in una discreta","Automatically translated"
"Copy & paste data","Copia e incolla i valori","Automatically translated"
"Copy / Paste","Copia / Incolla",""
"Count","Conteggio","Automatically translated"
"Create a new column","Crea una nuova colonna","Automatically translated"
"Create a new variable otherwise replaces the one selected","Crea una nuova variabile o sostituisci quella selezionata","Automatically translated"
"Create column","Crea una colunna","Automatically translated"
"Create factor variable","Crea una variabile discreta","Automatically translated"
"Data has %s observations and %s variables.","I dati hanno %s osservazioni e %s variabili.",""
"Data ready to be imported!","Dati pronti per l'importazione!","Automatically translated"
"Data successfully imported!","Dati importati con successo!",""
"Data successfully updated!","Dati aggiornati con successo!",""
"Data wasn't deleted","I dati non sono stati eliminati","Automatically translated"
"Data wasn't updated","I dati non sono stati aggiornati","Automatically translated"
"Dataset validation:","Validazione del dataset:","Automatically translated"
"Date format:","Formato della data:",""
"Date to use as origin to convert date/datetime:","Data da usare come origine per convertire le date:",""
"Decimal separator:","Separatore decimale:",""
"Delete","Elimina",""
"Do you want to delete the selected row ?","Vuoi eliminare la riga selezionata?",""
"Encoding:","Codifica:",""
"Enter URL to data:","Inserisci l'URL dei dati:","Automatically translated"
"Enter a shareable link to a GoogleSheet:","Inserisci un link condivisibile di GoogleSheet:",""
"Enter an expression to define new column:","Inserisci un'espressione per definire una nuova colonna:","Automatically translated"
"Environment","Ambiente",""
"Error","Errore",""
"External file","File",""
"Factor variable to reorder:","Variabile discreta da riordinare:","Automatically translated"
"Failed","Fallito",""
"First five rows are shown below:","Qui sotto sono mostrate le prime cinque righe:",""
"Googlesheets","Googlesheets",""
"Group calculation by:","Raggruppa per:","Automatically translated"
"Help","Aiuto",""
"How to import data?","Come importare i dati?",""
"Import","Importare",""
"Import Google Spreadsheet","Importa da Google Spreadsheet","Automatically translated"
"Import Url","URL per l'importazione","Automatically translated"
"Import a dataset from an environment","Importa il dataset da un'ambiente","Automatically translated"
"Import a file","Importare un file","Automatically translated"
"Import data","Importare dati",""
"Imported data","Dati importati","Automatically translated"
"Include lowest value","Includi il valore minore","Automatically translated"
"Information","Informazione",""
"Item has been modified","L'elemento è stato modificato",""
"Levels","Livelli","Automatically translated"
"List of data.frame...","Elenco dei data.frame...",""
"Max:","Massimo:","Automatically translated"
"Mean:","Media:","Automatically translated"
"Method:","Metodo:","Automatically translated"
"Min:","Minimo:","Automatically translated"
"Missing values characters:","Identificativo per i valori mancanti:","Automatically translated"
"Missing:","Mancante:","Automatically translated"
"Most Common:","Il più frequente:","Automatically translated"
"New column name cannot be empty","Il nome della nuova colonna non può essere vuoto","Automatically translated"
"New column name:","Nuovo nome della colonna:","Automatically translated"
"No","No",""
"No data selected!","Nessun dato selezionato!",""
"No data to display.","Nessun dato da mostrare.",""
"No data.frame here...","Nessun data.frame...",""
"No file selected","Nessun file selezionato",""
"No file selected:","Nessun file selezionato:",""
"Not a data.frame","Non è un data.frame","Automatically translated"
"Nothing pasted yet!","Non è ancora stato incollato nulla!",""
"Number of breaks:","Numero di intervalli:","Automatically translated"
"Number of rows:","Numero di righe:",""
"OK","OK",""
"Ooops","Ooops",""
"Paste data here:","Incolla i dati qui:",""
"Please copy and paste some data in the dialog box above.","Copia e incolla i dati nel riquadro sovrastante.",""
"Please fill in the required fields","Riempi i campi obbligatori",""
"Please paste a valid GoogleSheet link in the dialog box above.","Incolla un link valido di GoogleSheet nel riquadro sovrastante.",""
"Please paste a valid link in the dialog box above.","Incolla un link valido nel riquadro sovrastante.","Automatically translated"
"Registered","Registrato",""
"Required field","Campo obbligatorio",""
"Row has been saved","La riga è stata salvata",""
"Row was not deleted","La riga non è stata eliminata",""
"Rows to skip before reading data:","Righe da ignorare prima della lettura dei dati:","Automatically translated"
"Sample data by :","Campiona i dati per:","Automatically translated"
"Save","Salva",""
"Select","Seleziona",""
"Select a data.frame:","Seleziona un data.frame :",""
"Select an environment in which to search:","Seleziona un ambiente in cui cercare:",""
"Select environment","Seleziona un ambiente",""
"Select sheet to import:","Seleziona una scheda da importare:",""
"Some operations are not allowed","Alcune operazioni non sono permesse","Automatically translated"
"Something went wrong...","Qualcosa è andato storto...",""
"Sort count","Ordina i conteggi","Automatically translated"
"The URL that appear in your browser, in that case the current sheet will be read","L'URL nel tuo browser, in tal caso verrà letta la scheda corrente",""
"The row has been deleted","La riga è stata eliminata",""
"The row wasn't added to the data","La riga non è stata aggiunta ai dati","Automatically translated"
"URL","URL","Automatically translated"
"Unable to add the row, contact the platform administrator","Impossible aggiungere la riga, contatta l'amministratore del sistema",""
"Unable to delete the row, contact platform administrator","Impossible eliminare la riga, contatta l'amministratore del sistema",""
"Unable to modify the item, contact the platform administrator","Impossibile modificare l'elemento, contatta l'amministratore del sistema",""
"Unique values:","Valori unici:","Automatically translated"
"Unique:","Unico:","Automatically translated"
"Update","Aggiorna",""
"Update & select variables","Aggiorna e seleziona le variabili","Automatically translated"
"Update factor variable","Aggiorna la variabile discreta","Automatically translated"
"Update levels of a factor","Aggiorna i livelli della variabile discreta","Automatically translated"
"Update row","Aggiorna la riga",""
"Upload a file:","Carica un file:",""
"Use a data.frame from your environment or from the environment of a package.","Usa un data.frame nel tuo ambiente o in un pacchetto.",""
"Valid number of columns","Numero di colonne valido","Automatically translated"
"Valid number of rows","Numero di righe valido","Automatically translated"
"Validate","Validare",""
"Validation:","Validazione:","Automatically translated"
"Variable to cut:","Variabile da spezzare:","Automatically translated"
"View","Visualizza",""
"Warning","Attenzione","Automatically translated"
"Yes","Sì",""
"Yes","Sì",""
"You can either use:","Puoi usare:",""
"You can import %s files","Puoi importare %s file",""
"You can import from flat table format supported by","Puoi importare tabelle nel formato supportato da","Automatically translated"
"click to see data","clicca per vedere i dati","Automatically translated"
"data has %s obs. of %s variables.","i dati hanno %s osservazioni e %s variabili.",""
"if several use a comma ',' to separate them","se sono più d'uno separali con una virgola ','","Automatically translated"
"lines, i.e.","righe, cioé","Automatically translated"
"number of rows","numero di righe","Automatically translated"
"proportion of rows","proporzione delle righe","Automatically translated"
"rows","righe","Automatically translated"
"then enter an expression before clicking on the button above to validate or on ","quindi inserisci un'espressione prima di fare clic sul pulsante in alto per validare o su","Automatically translated"
"to delete it.","per eliminarlo.","Automatically translated"
"Sort by count","Ordina per conteggio","Automatically translated"
"Sort by levels","Ordina per livello","Automatically translated"
================================================
FILE: inst/i18n/ja.csv
================================================
label,translation,comment
"Import a dataset from an environment","Global environment からデータセットをインポート"
"Select a data.frame:","データフレームを選択:"
"List of data.frame...","データフレームのリスト"
"Select an environment in which to search:","検索する environment を選択:"
"Select environment","environment を選択"
"No data selected!","データが選択されていません!"
"Use a data.frame from your environment or from the environment of a package.","ユーザーの環境やパッケージからデータフレームを使用"
"No data.frame here...","データフレームがありません
"Ooops","おっと"
"Something went wrong...","問題が発生しました..."
"Data successfully imported!","データは正しくインポートされました!"
"Data ready to be imported!","データをインポートする準備ができました!"
"data has %s obs. of %s variables.","%s 行 %s 列のデータです。"
"click to see data","クリックしてデータを見る"
"Import data","データのインポート"
"Import a file","ファイルのインポート"
"Upload a file:","ファイルのアップロード:"
"Browse...","Browse..."
"No file selected","ファイルが選択されていません"
"Number of rows to skip before reading data:","データを読み込む前にスキップする行数:"
"Decimal separator:","小数点:"
"Encoding:","エンコード:"
"Select sheet to import:","インポートするシートを選択:"
"No file selected:","ファイルが選択されていません"
"You can import %s files","%s 個のファイルをインポートできます"
"First five rows are shown below:","最初の5行は以下の通り:"
"Copy & paste data","データをコピー/ペースト"
"Paste data here:","ここにデータをペースト:"
"Nothing pasted yet!","まだ何もペーストされていません!"
"Please copy and paste some data in the dialog box above.","上のダイアログボックスにデータをコピー&ペーストしてください。"
"Import Google Spreadsheet","Google スプレッドシートをインポート"
"You can either use:","こちらも利用できます:"
"A shareable link, in that case first sheet will be read","共有可能なリンク (先頭のシートが読み込まれます)"
"The URL that appear in your browser, in that case the current sheet will be read","ブラウザに表示されるリンク (現在のシートが読み込まれます)"
"Enter a shareable link to a GoogleSheet:","GoogleSheet への共有可能なリンクを入力 :"
"Please paste a valid GoogleSheet link in the dialog box above.","上記のダイアログボックスに有効な GoogleSheet のリンクをペーストしてください。"
"Help","ヘルプ"
"Environment","Environment"
"External file","外部データ"
"Copy / Paste","コピー/ペースト"
"Googlesheets","Googlesheets"
"How to import data?","データをインポートする方法?"
"Import","インポート"
"View","ビュー"
"Update","アップデート"
"Validate","検証"
"Update & select variables","変数の更新と選択"
"Date format:","日付のフォーマット:"
"Date to use as origin to convert date/datetime:","date/datetime への変換元として使用する Date:"
"Select, rename and convert variables in table above, then apply changes by clicking button below.","上の表で変数を選択、名前変更、変換し、下のボタンをクリックして変更を適用する。"
"Apply changes","変更を適用"
"Data has %s observations and %s variables.","%s 行 %s 列のデータです。"
"Data successfully updated!","データは正しく更新されました!"
"Validation:","検証:"
"OK","OK"
"Failed","失敗"
"Error","エラー"
"Number of rows:","行数:"
"No data to display.","表示するデータがありません"
"Close","閉じる"
"Add a label to data","データにラベルを追加"
"URL","URL"
"Add a row","行を追加"
"Required field","必須項目"
"Please fill in the required fields","必須項目を埋めてください"
"Unable to add the row, contact the platform administrator","行を追加できません。プラットフォームの管理者に連絡してください。"
"Registered","登録済み"
"Row has been saved","行データは保存されました"
"Update row","行を更新"
"Unable to modify the item, contact the platform administrator","項目を修正できません。プラットフォームの管理者に連絡してください。"
"Item has been modified","項目は修正されました"
"Delete","削除"
"Do you want to delete the selected row ?","選択した行を削除しますか?"
"Unable to delete the row, contact platform administrator",""行を削除できません。プラットフォームの管理者に連絡してください。"
"The row has been deleted","行は削除されました"
"Information","情報"
"Row was not deleted","行は削除されませんでした"
"Save","保存"
"Click to edit","クリックして編集"
"Click to delete","クリックして削除"
"Cancel","キャンセル"
"No","いいえ"
"Yes","はい"
"Edit data","データを編集"
"Select", "選択"
"Missing values character(s):","欠損値文字:"
"if several use a comma (',') to separate them","複数の場合はカンマ (「,」) を使用して区切ります"
================================================
FILE: inst/i18n/kr.csv
================================================
"label","translation","comment"
"% of the total","�꾩껜�� %","Automatically translated"
"% of the total, i.e.","�꾩껜�� %, 利�","Automatically translated"
"A shareable link, in that case first sheet will be read","공유 가능한 링크에서는 첫번째 Sheet가 사용됩니다.",""
"Add a label to data","데이터에 레이블 추가",""
"Add a row","행 추가",""
"Apply changes","적용",""
"Browse...","찾기",""
"Cancel","취소",""
"Choose a name for the column to be created or modified,","�앹꽦�섍굅�� �섏젙�� �댁쓽 �대쫫�� �좏깮�섍퀬,","Automatically translated"
"Choose a number of rows :","�� �섎� �좏깮�섏떗�쒖삤.","Automatically translated"
"Choose a percentage :","鍮꾩쑉�� �좏깮�섏꽭��:","Automatically translated"
"Click on a column name to add it to the expression:","�� �대쫫�� �대┃�섏뿬 �쒗쁽�앹뿉 異붽��⑸땲��.","Automatically translated"
"Click to delete","삭제하려면 클릭하세요.",""
"Click to edit","수정하려면 클릭하세요.",""
"Close","닫기",""
"Close intervals on the right","�ㅻⅨ履쎌쓽 媛꾧꺽 �リ린","Automatically translated"
"Column added!","移쇰읆�� 異붽��섏뿀�듬땲��!","Automatically translated"
"Convert Numeric to Factor","�レ옄瑜� �몄닔濡� 蹂��","Automatically translated"
"Copy & paste data","�곗씠�� 蹂듭궗 諛� 遺숈뿬�j린","Automatically translated"
"Copy / Paste","복사 / 붙여넣기",""
"Count","�몃떎","Automatically translated"
"Create a new column","�� �� 留뚮뱾湲�","Automatically translated"
"Create a new variable otherwise replaces the one selected","�� 蹂�섎� �앹꽦�섍굅�� 洹몃젃吏 �딆쑝硫� �좏깮�� 蹂�섎� �泥댄빀�덈떎.","Automatically translated"
"Create column","�� �앹꽦","Automatically translated"
"Create factor variable","�붿씤蹂�� �앹꽦","Automatically translated"
"Data has %s observations and %s variables.","%s행 %s 변수",""
"Data ready to be imported!","�곗씠�곕� 媛�몄삱 以鍮꾧� �섏뿀�듬땲��!","Automatically translated"
"Data successfully imported!","데이터 불러오기 성공",""
"Data successfully updated!","데이터 업데이트 성공",""
"Data wasn't deleted","�곗씠�곌� ��젣�섏� �딆븯�듬땲��.","Automatically translated"
"Data wasn't updated","�곗씠�곌� �낅뜲�댄듃�섏� �딆븯�듬땲��.","Automatically translated"
"Dataset validation:","�곗씠�곗꽭�� 寃利�:","Automatically translated"
"Date format:","날짜 포맷:",""
"Date to use as origin to convert date/datetime:","날짜/날짜/시간을 변환하기 위해 원 데이터로 사용할 날짜:",""
"Decimal separator:","소수점 구분 기호:",""
"Delete","삭제",""
"Do you want to delete the selected row ?","선택한 행을 삭제하시겠습니까?",""
"Encoding:","인코딩:",""
"Enter URL to data:","데이터 URL 입력:",""
"Enter a shareable link to a GoogleSheet:","공유 가능한 GoogleSheet 링크:",""
"Enter an expression to define new column:","�� �댁쓣 �뺤쓽�섎뒗 �쒗쁽�앹쓣 �낅젰�섏꽭��.","Automatically translated"
"Environment","환경 선택",""
"Error","에러",""
"External file","외부 파일",""
"Factor variable to reorder:","�ъ젙�ы븷 �붿씤 蹂��:","Automatically translated"
"Failed","실패",""
"First five rows are shown below:","泥섏쓬 5媛� �됱� �ㅼ쓬怨� 媛숈뒿�덈떎.","Automatically translated"
"Googlesheets","Googlesheets",""
"Group calculation by:","洹몃9 怨꾩궛 湲곗�:","Automatically translated"
"Help","도움말",""
"How to import data?","데이터 불러오기 방법",""
"Import","불러오기",""
"Import Google Spreadsheet","Google �ㅽ봽�덈뱶�쒗듃 媛�몄삤湲�","Automatically translated"
"Import Url","URL 媛�몄삤湲�","Automatically translated"
"Import a dataset from an environment","�섍꼍�먯꽌 �곗씠�곗꽭�� 媛�몄삤湲�","Automatically translated"
"Import a file","�뚯씪 媛�몄삤湲�","Automatically translated"
"Import data","데이터 불러오기",""
"Imported data","媛�몄삩 �곗씠��","Automatically translated"
"Include lowest value","媛�� ��� 媛� �ы븿","Automatically translated"
"Information","정보",""
"Item has been modified","항목이 수정되었습니다",""
"Levels","�덈꺼","Automatically translated"
"List of data.frame...","data.frame 리스트",""
"Max:","理쒕�:","Automatically translated"
"Mean:","�됯퇏:","Automatically translated"
"Method:","諛⑸쾿:","Automatically translated"
"Min:","理쒖냼:","Automatically translated"
"Missing values characters:","�꾨씫�� 媛� 臾몄옄:","Automatically translated"
"Missing:","�놁뼱吏�:","Automatically translated"
"Most Common:","媛�� �뷀븳:","Automatically translated"
"New column name cannot be empty","�� �� �대쫫� 鍮꾩썙�� �� �놁뒿�덈떎.","Automatically translated"
"New column name:","�� �� �대쫫:","Automatically translated"
"No","아니",""
"No data selected!","데이터 선택되지 않음!",""
"No data to display.","화면에 나타낼 데이터 없음.",""
"No data.frame here...","여기에 data.frame이 없습니다...",""
"No file selected","파일 선택되지 않음:",""
"No file selected:","파일 선택되지 않음:",""
"Not a data.frame","data.frame�� �꾨떃�덈떎.","Automatically translated"
"Nothing pasted yet!","아무것도 붙여넣기되지 않음!",""
"Number of breaks:","�댁떇 �잛닔:","Automatically translated"
"Number of rows:","열 수",""
"OK","OK",""
"Ooops","에러",""
"Paste data here:","여기에 데이터 붙여넣기:",""
"Please copy and paste some data in the dialog box above.","위의 상자에 데이터를 붙여넣으세요.",""
"Please fill in the required fields","필수 필드를 작성하십시오",""
"Please paste a valid GoogleSheet link in the dialog box above.","위의 상자에 유효한 GoogleSheet 링크를 붙여넣으세요.",""
"Please paste a valid link in the dialog box above.","위의 대화 상자에 유효한 링크를 붙여넣으십시오.",""
"Registered","등기",""
"Required field","필수 입력란",""
"Row has been saved","행이 저장되었습니다.",""
"Row was not deleted","행이 삭제되지 않았습니다.",""
"Rows to skip before reading data:","�곗씠�곕� �쎄린 �꾩뿉 嫄대꼫�� ��:","Automatically translated"
"Sample data by :","�섑뵆 �곗씠�� 湲곗�:","Automatically translated"
"Save","구하다",""
"Select","고르다",""
"Select a data.frame:","Data Frame 선택:",""
"Select an environment in which to search:","찾을 환경 선택",""
"Select environment","환경 선택",""
"Select sheet to import:","불러올 Sheet 선택:",""
"Some operations are not allowed","�쇰� �묒뾽� �덉슜�섏� �딆뒿�덈떎","Automatically translated"
"Something went wrong...","臾몄젣媛 諛쒖깮�덉뒿�덈떎.","Automatically translated"
"Sort count","�뺣젹 �잛닔","Automatically translated"
"The URL that appear in your browser, in that case the current sheet will be read","브라우저에 나타난 URL을 붙여넣으면 현재 보고 있는 Sheet가 사용됩니다.",""
"The row has been deleted","행이 삭제되었습니다.",""
"The row wasn't added to the data","�됱씠 �곗씠�곗뿉 異붽��섏� �딆븯�듬땲��.","Automatically translated"
"URL","URL",""
"Unable to add the row, contact the platform administrator","행을 추가할 수 없습니다. 플랫폼 관리자에게 문의하세요.",""
"Unable to delete the row, contact platform administrator","행을 삭제할 수 없습니다. 플랫폼 관리자에게 문의하세요.",""
"Unable to modify the item, contact the platform administrator","항목을 수정할 수 없습니다. 플랫폼 관리자에게 문의하세요.",""
"Unique values:","怨좎쑀�� 媛�:","Automatically translated"
"Unique:","怨좎쑀��:","Automatically translated"
"Update","업데이트",""
"Update & select variables","蹂�� �낅뜲�댄듃 諛� �좏깮","Automatically translated"
"Update factor variable","�붿씤 蹂�� �낅뜲�댄듃","Automatically translated"
"Update levels of a factor","�붿씤 �섏� �낅뜲�댄듃","Automatically translated"
"Update row","행 업데이트",""
"Upload a file:","파일 업로드:",""
"Use a data.frame from your environment or from the environment of a package.","사용자 환경이나 패키지로부터 data.frame을 불러와 사용하세요.",""
"Valid number of columns","�좏슚�� �� ��","Automatically translated"
"Valid number of rows","�좏슚�� �� ��","Automatically translated"
"Validate","검증",""
"Validation:","�뺤씤:","Automatically translated"
"Variable to cut:","�섎씪�� 蹂��:","Automatically translated"
"View","보기",""
"Warning","寃쎄퀬","Automatically translated"
"Yes","예",""
"You can either use:","다음 중 선택:",""
"You can import %s files","%s 파일 불러오기 가능",""
"You can import from flat table format supported by","에서 지원하는 플랫 테이블 형식에서 가져올 수 있습니다.",""
"click to see data","�곗씠�곕� 蹂대젮硫� �대┃�섏꽭��","Automatically translated"
"data has %s obs. of %s variables.","%s행 변수 %s",""
"if several use a comma ',' to separate them","�щ윭 紐낆씠 �쇳몴 ','瑜� �ъ슜�섏뿬 援щ텇�섎뒗 寃쎌슦","Automatically translated"
"lines, i.e.","�쇱씤, 利�","Automatically translated"
"number of rows","�� ��","Automatically translated"
"proportion of rows","�됱쓽 鍮꾩쑉","Automatically translated"
"rows","��","Automatically translated"
"then enter an expression before clicking on the button above to validate or on ","洹몃윴 �ㅼ쓬 �꾩쓽 踰꾪듉�� �대┃�섍린 �꾩뿉 �쒗쁽�앹쓣 �낅젰�섏뿬 �좏슚�깆쓣 寃�ы븯嫄곕굹","Automatically translated"
"to delete it.","��젣�섎젮硫�","Automatically translated"
"Sort by count","媛쒖닔蹂꾨줈 �뺣젹","Automatically translated"
"Sort by levels","�덈꺼蹂꾨줈 �뺣젹","Automatically translated"
================================================
FILE: inst/i18n/maj_csv.R
================================================
library(data.table)
library(stringr)
library(utils)
library(polyglotr)
source("inst/i18n/extract_labels.R")
# Extraction of labels contained in the “/R” subdirectory
extraction_labels <- c(extract_labels(folder = "R"))
# Updating csv with previously extracted labels WITHOUT translation
update_csv(labels = extraction_labels, lang = "fr", lang_csv = "fr", translation = FALSE)
update_csv(labels = extraction_labels, lang = "es", lang_csv = "es", translation = FALSE)
update_csv(labels = extraction_labels, lang = "de", lang_csv = "de", translation = FALSE)
update_csv(labels = extraction_labels, lang = "sq", lang_csv = "al", translation = FALSE)
update_csv(labels = extraction_labels, lang = "pl", lang_csv = "pl", translation = FALSE)
update_csv(labels = extraction_labels, lang = "pt", lang_csv = "pt", translation = FALSE)
update_csv(labels = extraction_labels, lang = "tr", lang_csv = "tr", translation = FALSE)
update_csv(labels = extraction_labels, lang = "mk", lang_csv = "mk", translation = FALSE)
# update_csv(labels = extraction_labels, lang = "ja", lang_csv = "ja", translation = FALSE, encoding = "ISO_2022,locale=ja,version=4") # review encoding
update_csv(labels = extraction_labels, lang = "zh-CN", lang_csv = "cn", translation = FALSE, encoding = "GBK") #"UTF16_BigEndian" or "GB18030"
update_csv(labels = extraction_labels, lang = "ko", lang_csv = "kr", translation = FALSE, encoding = "korean") # "GBK", "korean"
# Updating csv with labels extracted previously WITH translation
update_csv(labels = extraction_labels, lang = "fr", lang_csv = "fr")
update_csv(labels = extraction_labels, lang = "es", lang_csv = "es")
update_csv(labels = extraction_labels, lang = "de", lang_csv = "de")
update_csv(labels = extraction_labels, lang = "sq", lang_csv = "al")
update_csv(labels = extraction_labels, lang = "pl", lang_csv = "pl")
update_csv(labels = extraction_labels, lang = "pt", lang_csv = "pt")
update_csv(labels = extraction_labels, lang = "tr", lang_csv = "tr")
update_csv(labels = extraction_labels, lang = "mk", lang_csv = "mk")
# update_csv(labels = extraction_labels, lang = "ja", lang_csv = "ja", encoding = "ISO_2022,locale=ja,version=4") # review encoding
update_csv(labels = extraction_labels, lang = "zh-CN", lang_csv = "cn", encoding = "GBK") #"UTF16_BigEndian" or "GB18030"
update_csv(labels = extraction_labels, lang = "ko", lang_csv = "kr", encoding = "korean") # "GBK", "korean"
================================================
FILE: inst/i18n/mk.csv
================================================
"label","translation","comment"
"% of the total","% од вкупниот број","Automatically translated"
"% of the total, i.e.","% од вкупниот број, т.е.","Automatically translated"
"A shareable link, in that case first sheet will be read","Врска којашто може да се сподели, во овој случај првата страна ќе биде прочитана",""
"Add a label to data","Додадете етикета на податоците","#TODO #CHECK"
"Add a row","Додадете ред",""
"Apply changes","Применете ги промените",""
"Browse...","Пребарувајте...",""
"Cancel","Откажи",""
"Choose a name for the column to be created or modified,","Изберете име за колоната што треба да се креира или измени,","Automatically translated"
"Choose a number of rows :","Изберете голем број редови:","Automatically translated"
"Choose a percentage :","Изберете процент:","Automatically translated"
"Click on a column name to add it to the expression:","Кликнете на името на колоната за да го додадете во изразот:","Automatically translated"
"Click to delete","Кликнете за да избришете",""
"Click to edit","Кликнете за уредување",""
"Close","Затвори",""
"Close intervals on the right","Затворете ги интервалите од десната страна","Automatically translated"
"Column added!","Колона е додадена!","Automatically translated"
"Convert Numeric to Factor","Конвертирај нумерички во фактор","Automatically translated"
"Copy & paste data","Копирајте и залепете податоци",""
"Copy / Paste","Копирај / залепи",""
"Count","брои","Automatically translated"
"Create a new column","Направете нова колона","Automatically translated"
"Create a new variable otherwise replaces the one selected","Креирајте нова променлива инаку ја заменува избраната","Automatically translated"
"Create column","Креирај колона","Automatically translated"
"Create factor variable","Креирај променлива на фактор","Automatically translated"
"Data has %s observations and %s variables.","Податоците имаат %s опсервации и %s варијабли.",""
"Data ready to be imported!","Податоци коишто се спремни за да бидат увезени",""
"Data successfully imported!","Успешно увезени податоци",""
"Data successfully updated!","Податоците се успешно ажурирани!",""
"Data wasn't deleted","Податоците не се избришани","Automatically translated"
"Data wasn't updated","Податоците не беа ажурирани","Automatically translated"
"Dataset validation:","Потврда на сет на податоци:","Automatically translated"
"Date format:","Формат на датум:",""
"Date to use as origin to convert date/datetime:","Датум што треба да се користи за конвертирање на date/datetime променлива",""
"Decimal separator:","Децимален раздвојник:",""
"Delete","Избриши",""
"Do you want to delete the selected row ?","Дали сакате да го избришете избраниот ред?",""
"Encoding:","Енкодинг:",""
"Enter URL to data:","Внесете URL на податоците:","Automatically translated"
"Enter a shareable link to a GoogleSheet:","Внесете врска којшто може да се сподели во GoogleSheet:",""
"Enter an expression to define new column:","Внесете израз за да дефинирате нова колона:","Automatically translated"
"Environment","Околина",""
"Error","Грешка",""
"External file","Надворешна датотека",""
"Factor variable to reorder:","Факторска променлива за прередување:","Automatically translated"
"Failed","Неуспех",""
"First five rows are shown below:","Првите пет реда се прикажани подолу:",""
"Googlesheets","Googlesheets",""
"Group calculation by:","Групна пресметка според:","Automatically translated"
"Help","Помош",""
"How to import data?","Како да се увезат податоците?",""
"Import","Увези",""
"Import Google Spreadsheet","Увезете GoogleSheet",""
"Import Url","Увезете УРЛ","Automatically translated"
"Import a dataset from an environment","Увезете податочен сет од околината",""
"Import a file","Внесете документ",""
"Import data","Внесете податоци",""
"Imported data","Увезени податоци","Automatically translated"
"Include lowest value","Вклучете ја најниската вредност","Automatically translated"
"Information","Информации",""
"Item has been modified","Ставката е изменета",""
"Levels","Нивоа","Automatically translated"
"List of data.frame...","Список на табели со податоци",""
"Max:","Макс:","Automatically translated"
"Mean:","Средно:","Automatically translated"
"Method:","Метод:","Automatically translated"
"Min:","Мин:","Automatically translated"
"Missing values characters:","Недостасуваат знаци на вредности:","Automatically translated"
"Missing:","Недостасува:","Automatically translated"
"Most Common:","Најчесто:","Automatically translated"
"New column name cannot be empty","Името на новата колона не може да биде празно","Automatically translated"
"New column name:","Ново име на колона:","Automatically translated"
"No","бр",""
"No data selected!","Нема ниту еден избран податок",""
"No data to display.","Нема податоци за приказ.",""
"No data.frame here...","Тука нема податоци...",""
"No file selected","Ниту еден документ не е избран",""
"No file selected:","Ниту еден документ не е избран",""
"Not a data.frame","Не е податок.рамка","Automatically translated"
"Nothing pasted yet!","Ништо до сега не е залепено!",""
"Number of breaks:","Број на паузи:","Automatically translated"
"Number of rows:","Број на редови:",""
"OK","Во ред",""
"Ooops","Упс",""
"Paste data here:","Залепете ги вашите податоци тука:",""
"Please copy and paste some data in the dialog box above.","Ве молиме копирајте и залепете некои податоци во прозорчето за дијалог подолу",""
"Please fill in the required fields","Ве молиме пополнете ги бараните полиња",""
"Please paste a valid GoogleSheet link in the dialog box above.","Ве молиме залепете валидна врска до GoogleSheet во прозорчето подолу.",""
"Please paste a valid link in the dialog box above.","Ве молиме залепете валидна врска во полето за дијалог погоре.","Automatically translated"
"Registered","Регистриран",""
"Required field","задолжително поле",""
"Row has been saved","Редот е зачуван",""
"Row was not deleted","Редот не беше избришан",""
"Rows to skip before reading data:","Редови што треба да се прескокнат пред да се прочитаат податоците:","Automatically translated"
"Sample data by :","Примерок на податоци од:","Automatically translated"
"Save","Зачувај",""
"Select","изберете",""
"Select a data.frame:","Изберете data.frame",""
"Select an environment in which to search:","Изберете околина за пребарување",""
"Select environment","Изберете околина",""
"Select sheet to import:","Изберете лист за да увезете",""
"Some operations are not allowed","Некои операции не се дозволени","Automatically translated"
"Something went wrong...","Тука нема податоци...",""
"Sort count","Броење сортирање","Automatically translated"
"The URL that appear in your browser, in that case the current sheet will be read","URL коешто се појавува во вашиот пребарарувач, во овој случај првата страна ќе биде прочитана",""
"The row has been deleted","Редот е избришан",""
"The row wasn't added to the data","Редот не беше додаден на податоците","Automatically translated"
"URL","URL","Automatically translated"
"Unable to add the row, contact the platform administrator","Не може да се додаде редот, контактирајте со администраторот на платформата",""
"Unable to delete the row, contact platform administrator","Не може да се избрише редот, контактирајте со администраторот на платформата",""
"Unable to modify the item, contact the platform administrator","Не може да се измени ставката, контактирајте со администраторот на платформата",""
"Unique values:","Единствени вредности:","Automatically translated"
"Unique:","Уникатно:","Automatically translated"
"Update","Ажурирај",""
"Update & select variables","Ажурирај и одбери променливи",""
"Update factor variable","Ажурирајте ја променливата на факторот","Automatically translated"
"Update levels of a factor","Ажурирајте ги нивоата на фактор","Automatically translated"
"Update row","Ажурирајте го редот",""
"Upload a file:","Прикачете документ",""
"Use a data.frame from your environment or from the environment of a package.","Користете data.frame од твојата околина или од пакет",""
"Valid number of columns","Валиден број на колони","Automatically translated"
"Valid number of rows","Валиден број на редови","Automatically translated"
"Validate","Провери",""
"Validation:","Проверка:",""
"Variable to cut:","Променлива за сечење:","Automatically translated"
"View","Прегледај",""
"Warning","Предупредување","Automatically translated"
"Yes","Да",""
"You can either use:","Можете да користите нешто од ова:",""
"You can import %s files","Можете да увезувате документи %s",""
"You can import from flat table format supported by","Можете да увезете од формат на рамна табела поддржан од","Automatically translated"
"click to see data","Притиснете тука за да прикачите податоци",""
"data has %s obs. of %s variables.","Податоците имаат % обсерваци и % променливи",""
"if several use a comma ',' to separate them","ако неколку користат запирка ',' за да ги разделат","Automatically translated"
"lines, i.e.","линии, т.е.","Automatically translated"
"number of rows","број на редови","Automatically translated"
"proportion of rows","пропорција на редови","Automatically translated"
"rows","редови","Automatically translated"
"then enter an expression before clicking on the button above to validate or on ","потоа внесете израз пред да кликнете на копчето погоре за да потврдите или да го вклучите","Automatically translated"
"to delete it.","да го избришете.","Automatically translated"
"Sort by count","Подреди по број","Automatically translated"
"Sort by levels","Подреди по нивоа","Automatically translated"
================================================
FILE: inst/i18n/pl.csv
================================================
"label","translation","comment"
"% of the total","% całkowitej","Automatically translated"
"% of the total, i.e.","% całości, tj.","Automatically translated"
"A shareable link, in that case first sheet will be read","Linku do udostępniania (zostanie odczytany pierwszy arkusz)",""
"Add a label to data","Dodaj etykietę do danych",""
"Add a row","Dodaj wiersz",""
"Apply changes","Zastosuj zmiany",""
"Browse...","Przeglądaj...",""
"Cancel","Anuluj",""
"Choose a name for the column to be created or modified,","Wybierz nazwę kolumny, która ma zostać utworzona lub zmodyfikowana,","Automatically translated"
"Choose a number of rows :","Wybierz liczbę wierszy:","Automatically translated"
"Choose a percentage :","Wybierz procent:","Automatically translated"
"Click on a column name to add it to the expression:","Kliknij nazwę kolumny, aby dodać ją do wyrażenia:","Automatically translated"
"Click to delete","Naciśnij by usunąć",""
"Click to edit","Naciśnij by edytować",""
"Close","Zamknij.",""
"Close intervals on the right","Zamknij odstępy po prawej stronie","Automatically translated"
"Column added!","Dodano kolumnę!","Automatically translated"
"Convert Numeric to Factor","Zamień liczbę na współczynnik","Automatically translated"
"Copy & paste data","Kopiuj i wklej dane",""
"Copy / Paste","Kopiuj / wklej",""
"Count","Liczyć","Automatically translated"
"Create a new column","Utwórz nową kolumnę","Automatically translated"
"Create a new variable otherwise replaces the one selected","Utwórz nową zmienną, w przeciwnym razie zastępuje wybraną","Automatically translated"
"Create column","Utwórz kolumnę","Automatically translated"
"Create factor variable","Utwórz zmienną czynnikową","Automatically translated"
"Data has %s observations and %s variables.","dane zawierają %s obserwacji i %s zmiennych.",""
"Data ready to be imported!","Dane gotowe do importu!",""
"Data successfully imported!","Dane zaimportowano pomyślnie!",""
"Data successfully updated!","Dane pomyślnie zaktualizowano",""
"Data wasn't deleted","Dane nie zostały usunięte","Automatically translated"
"Data wasn't updated","Dane nie zostały zaktualizowane","Automatically translated"
"Dataset validation:","Walidacja zbioru danych:","Automatically translated"
"Date format:","Format dat:",""
"Date to use as origin to convert date/datetime:","Data do użycia jako początkowa do konwersji dat/dat i czasu",""
"Decimal separator:","Separator dziesiętny:",""
"Delete","Usuń",""
"Do you want to delete the selected row ?","Czy na pewo chcesz usunąć ten wiersz?",""
"Encoding:","Kodowanie:",""
"Enter URL to data:","Wpisz adres URL do danych:","Automatically translated"
"Enter a shareable link to a GoogleSheet:","Wprowadź link do udostępniania Arkusza Google:",""
"Enter an expression to define new column:","Wprowadź wyrażenie definiujące nową kolumnę:","Automatically translated"
"Environment","Środowisko",""
"Error","Błąd",""
"External file","Plik zewnętrzny",""
"Factor variable to reorder:","Zmienna czynnikowa do zmiany kolejności:","Automatically translated"
"Failed","Nie udało się",""
"First five rows are shown below:","Poniżej pokazano pięć pierwszych wierszy:",""
"Googlesheets","Arkusze Google",""
"Group calculation by:","Obliczenia grupowe według:","Automatically translated"
"Help","Pomoc",""
"How to import data?","Jak zaimportować dane?",""
"Import","Importuj",""
"Import Google Spreadsheet","Importuj z Arkuszy Google",""
"Import Url","Importuj adres URL","Automatically translated"
"Import a dataset from an environment","Importuj dane ze środowiska",""
"Import a file","Importuj plik",""
"Import data","Importuj dane",""
"Imported data","Zaimportowane dane","Automatically translated"
"Include lowest value","Uwzględnij najniższą wartość","Automatically translated"
"Information","Informacje",""
"Item has been modified","Obiekt został zmieniony",""
"Levels","Poziomy","Automatically translated"
"List of data.frame...","Lista obiektów data.frame...",""
"Max:","Maks:","Automatically translated"
"Mean:","Mieć na myśli:","Automatically translated"
"Method:","Metoda:","Automatically translated"
"Min:","Min.:","Automatically translated"
"Missing values characters:","Brakujące znaki wartości:","Automatically translated"
"Missing:","Zaginiony:","Automatically translated"
"Most Common:","Najczęściej:","Automatically translated"
"New column name cannot be empty","Nazwa nowej kolumny nie może być pusta","Automatically translated"
"New column name:","Nowa nazwa kolumny:","Automatically translated"
"No","Nie",""
"No data selected!","Nie wybrano danych!",""
"No data to display.","Brak danych do wyświetlenia.",""
"No data.frame here...","Brak obiektów data.frame",""
"No file selected","Nie wybrano żadnego pliku",""
"No file selected:","Nie wybrano pliku:",""
"Not a data.frame","Nie ramka danych","Automatically translated"
"Nothing pasted yet!","Jeszcze nic nie wklejono!",""
"Number of breaks:","Liczba przerw:","Automatically translated"
"Number of rows:","Liczba wierszy:",""
"OK","OK",""
"Ooops","Upsss",""
"Paste data here:","Wklej dane tutaj:",""
"Please copy and paste some data in the dialog box above.","Proszę skopiować i wkleić dane do okienka powyżej.",""
"Please fill in the required fields","Proszę wypełnić wymagane pola",""
"Please paste a valid GoogleSheet link in the dialog box above.","Proszę wprowadzić popeawny link do Arkusza Google w okienku powyżej.",""
"Please paste a valid link in the dialog box above.","Wklej prawidłowy link w powyższym oknie dialogowym.","Automatically translated"
"Registered","Zarejestrowano",""
"Required field","Pole wymagane",""
"Row has been saved","Wiersz został zapisany",""
"Row was not deleted","Wiersz nie został usunięty",""
"Rows to skip before reading data:","Wiersze do pominięcia przed odczytaniem danych:","Automatically translated"
"Sample data by :","Przykładowe dane według:","Automatically translated"
"Save","Ratować",""
"Select","Wybierz",""
"Select a data.frame:","Wybierz data.frame:",""
"Select an environment in which to search:","Wybierz środowisko, w którym chcesz szukać:",""
"Select environment","Wybierz środowisko",""
"Select sheet to import:","Wybierz arkusz:",""
"Some operations are not allowed","Niektóre operacje są niedozwolone","Automatically translated"
"Something went wrong...","Coś poszło nie tak...",""
"Sort count","Liczba sortowań","Automatically translated"
"The URL that appear in your browser, in that case the current sheet will be read","Linku z przeglądarki (zostanie odczytany aktualny arkusz)",""
"The row has been deleted","Wiersz został usunięty",""
"The row wasn't added to the data","Wiersz nie został dodany do danych","Automatically translated"
"URL","URL",""
"Unable to add the row, contact the platform administrator","Brak możliwości dodania wiersza, skontaktuj się z administratorem",""
"Unable to delete the row, contact platform administrator","Brak możliwości usunięcia wiersza, skontaktuj się z administratorem",""
"Unable to modify the item, contact the platform administrator","Brak możliwości modyfikacji obiektu, skontaktuj się z administratorem",""
"Unique values:","Unikalne wartości:","Automatically translated"
"Unique:","Unikalny:","Automatically translated"
"Update","Zaktualizuj",""
"Update & select variables","Zaktualizuj i wybierz zmienne",""
"Update factor variable","Aktualizuj zmienną współczynnika","Automatically translated"
"Update levels of a factor","Aktualizuj poziomy czynnika","Automatically translated"
"Update row","Zaktualizuj wiersz",""
"Upload a file:","Wgraj plik:",""
"Use a data.frame from your environment or from the environment of a package.","Użyj obiektu data.frame ze swojego środowiska lub ze środowiska pakietu.",""
"Valid number of columns","Prawidłowa liczba kolumn","Automatically translated"
"Valid number of rows","Prawidłowa liczba wierszy","Automatically translated"
"Validate","Sprawdź",""
"Validation:","Sprawdzenie:",""
"Variable to cut:","Zmienna do cięcia:","Automatically translated"
"View","Pokaż",""
"Warning","Ostrzeżenie","Automatically translated"
"Yes","Tak",""
"You can either use:","Możesz użyć:",""
"You can import %s files","Możesz zaimportować %s plików",""
"You can import from flat table format supported by","Możesz importować z formatu płaskiej tabeli obsługiwanego przez","Automatically translated"
"click to see data","kliknij by zobaczyć dane",""
"data has %s obs. of %s variables.","dane zawierają %s obserwacji %s zmiennych.",""
"if several use a comma ',' to separate them","jeśli kilka z nich użyje przecinka „,” aby je oddzielić","Automatically translated"
"lines, i.e.","linie, tj.","Automatically translated"
"number of rows","Liczba rzędów","Automatically translated"
"proportion of rows","proporcja rzędów","Automatically translated"
"rows","wydziwianie","Automatically translated"
"then enter an expression before clicking on the button above to validate or on ","następnie wprowadź wyrażenie przed kliknięciem przycisku powyżej, aby zatwierdzić lub włączyć","Automatically translated"
"to delete it.","aby go usunąć.","Automatically translated"
"Sort by count","Sortuj według liczby","Automatically translated"
"Sort by levels","Sortuj według poziomów","Automatically translated"
================================================
FILE: inst/i18n/pt.csv
================================================
"label","translation","comment"
"% of the total","% do total","Automatically translated"
"% of the total, i.e.","% do total, ou seja,","Automatically translated"
"A shareable link, in that case first sheet will be read","Um link compartilhável, nesse caso a primeira aba será lida",""
"Add a label to data","Adicionar uma etiqueta aos dados","#TODO #CHECK"
"Add a row","Adicionar uma linha",""
"Apply changes","Aplique as mudanças",""
"Browse...","Buscar...",""
"Cancel","Cancelar",""
"Choose a name for the column to be created or modified,","Escolha um nome para a coluna a ser criada ou modificada,","Automatically translated"
"Choose a number of rows :","Escolha um número de linhas:","Automatically translated"
"Choose a percentage :","Escolha uma porcentagem:","Automatically translated"
"Click on a column name to add it to the expression:","Clique no nome de uma coluna para adicioná-la à expressão:","Automatically translated"
"Click to delete","Clique para deletar",""
"Click to edit","Clique para editar",""
"Close","Fechar",""
"Close intervals on the right","Intervalos próximos à direita","Automatically translated"
"Column added!","Coluna adicionada!","Automatically translated"
"Convert Numeric to Factor","Converter numérico em fator","Automatically translated"
"Copy & paste data","Copie & cole os dados",""
"Copy / Paste","Copie / Cole",""
"Count","Contar","Automatically translated"
"Create a new column","Crie uma nova coluna","Automatically translated"
"Create a new variable otherwise replaces the one selected","Crie uma nova variável, caso contrário substituirá a selecionada","Automatically translated"
"Create column","Criar coluna","Automatically translated"
"Create factor variable","Criar variável de fator","Automatically translated"
"Data has %s observations and %s variables.","Os dados possuem %s observações de %s variáveis.",""
"Data ready to be imported!","Dados prontos para serem importados!",""
"Data successfully imported!","Dados importados com sucesso!",""
"Data successfully updated!","Os dados foram modificados com sucesso!",""
"Data wasn't deleted","Os dados não foram excluídos","Automatically translated"
"Data wasn't updated","Os dados não foram atualizados","Automatically translated"
"Dataset validation:","Validação do conjunto de dados:","Automatically translated"
"Date format:","Formato dos dados:",""
"Date to use as origin to convert date/datetime:","Data para usar como origem para converter date/datetime:",""
"Decimal separator:","Separador decimal:",""
"Delete","Excluir",""
"Do you want to delete the selected row ?","Deseja excluir a linha selecionada?",""
"Encoding:","Encoding:",""
"Enter URL to data:","Insira o URL para os dados:","Automatically translated"
"Enter a shareable link to a GoogleSheet:","Coloque um link compartilhável para o GoogleSheet:",""
"Enter an expression to define new column:","Insira uma expressão para definir a nova coluna:","Automatically translated"
"Environment","Ambiente local",""
"Error","Erro",""
"External file","Arquivo externo",""
"Factor variable to reorder:","Variável de fator para reordenar:","Automatically translated"
"Failed","Falha",""
"First five rows are shown below:","As cinco primeiras linhas são mostradas abaixo:",""
"Googlesheets","Googlesheets",""
"Group calculation by:","Cálculo do grupo por:","Automatically translated"
"Help","Ajuda",""
"How to import data?","Como importar os dados?",""
"Import","Importar",""
"Import Google Spreadsheet","Importe um Spreadsheet do Google",""
"Import Url","Url de importação","Automatically translated"
"Import a dataset from an environment","Importe um conjunto de dados do ambiente local",""
"Import a file","Importe um arquivo",""
"Import data","Importe os dados",""
"Imported data","Dados importados","Automatically translated"
"Include lowest value","Incluir o valor mais baixo","Automatically translated"
"Information","Em formação",""
"Item has been modified","O item foi modificado",""
"Levels","Níveis","Automatically translated"
"List of data.frame...","Lista de data.frame...",""
"Max:","Máx.:","Automatically translated"
"Mean:","Significar:","Automatically translated"
"Method:","Método:","Automatically translated"
"Min:","Mínimo:","Automatically translated"
"Missing values characters:","Caracteres de valores ausentes:","Automatically translated"
"Missing:","Ausente:","Automatically translated"
"Most Common:","Mais comum:","Automatically translated"
"New column name cannot be empty","O novo nome da coluna não pode ficar vazio","Automatically translated"
"New column name:","Novo nome de coluna:","Automatically translated"
"No","Não",""
"No data selected!","Nenhum dado foi selecionado!",""
"No data to display.","Nenhum dado para mostrar.",""
"No data.frame here...","Nenhum data.frame aqui...",""
"No file selected","Nenhum arquivo selecionado",""
"No file selected:","Nenhum arquivo selecionado:",""
"Not a data.frame","Não é um data.frame","Automatically translated"
"Nothing pasted yet!","Nada foi colado ainda!",""
"Number of breaks:","Número de pausas:","Automatically translated"
"Number of rows:","Número de linhas:",""
"OK","OK",""
"Ooops","Ooops",""
"Paste data here:","Cole os dados aqui:",""
"Please copy and paste some data in the dialog box above.","Por favor, copie e cole algum dado na caixa de diálogo acima.",""
"Please fill in the required fields","Por favor, preencha os campos obrigatórios",""
"Please paste a valid GoogleSheet link in the dialog box above.","Por favor, cole um link válido para o GoogleSheet na caixa de diálogo acima.",""
"Please paste a valid link in the dialog box above.","Cole um link válido na caixa de diálogo acima.","Automatically translated"
"Registered","Registrado",""
"Required field","Campo obrigatório",""
"Row has been saved","A linha foi salva",""
"Row was not deleted","A linha não foi excluída",""
"Rows to skip before reading data:","Linhas a serem ignoradas antes da leitura dos dados:","Automatically translated"
"Sample data by :","Dados de amostra por:","Automatically translated"
"Save","Salvar",""
"Select","Selecionar",""
"Select a data.frame:","Selecione um data.frame :",""
"Select an environment in which to search:","Selecione um ambiente local para a busca:",""
"Select environment","Selecione um ambiente local",""
"Select sheet to import:","Selecione uma aba para importar:",""
"Some operations are not allowed","Algumas operações não são permitidas","Automatically translated"
"Something went wrong...","Algo deu errado...",""
"Sort count","Contagem de classificação","Automatically translated"
"The URL that appear in your browser, in that case the current sheet will be read","A URL que aparece no seu navegador, nesse caso a aba atual será lida",""
"The row has been deleted","A linha foi excluída",""
"The row wasn't added to the data","A linha não foi adicionada aos dados","Automatically translated"
"URL","URL","Automatically translated"
"Unable to add the row, contact the platform administrator","Não é possível adicionar a linha, entre em contato com o administrador da plataforma",""
"Unable to delete the row, contact platform administrator","Não é possível excluir a linha, entre em contato com o administrador da plataforma",""
"Unable to modify the item, contact the platform administrator","Não é possível modificar o item, entre em contato com o administrador da plataforma",""
"Unique values:","Valores únicos:","Automatically translated"
"Unique:","Exclusivo:","Automatically translated"
"Update","Modifique",""
"Update & select variables","Carregue & selecione variáveis",""
"Update factor variable","Variável de fator de atualização","Automatically translated"
"Update levels of a factor","Atualizar níveis de um fator","Automatically translated"
"Update row","Atualizar linha",""
"Upload a file:","Carregue um arquivo:",""
"Use a data.frame from your environment or from the environment of a package.","Use um data.frame do seu ambiente local ou do ambiente de um pacote.",""
"Valid number of columns","Número válido de colunas","Automatically translated"
"Valid number of rows","Número válido de linhas","Automatically translated"
"Validate","Validação",""
"Validation:","Validação:",""
"Variable to cut:","Variável para cortar:","Automatically translated"
"View","Visualizar",""
"Warning","Aviso","Automatically translated"
"Yes","Sim",""
"You can either use:","Você pode usar:",""
"You can import %s files","Você pode importar %s",""
"You can import from flat table format supported by","Você pode importar do formato de tabela plana suportado por","Automatically translated"
"click to see data","clique para visualizar os dados",""
"data has %s obs. of %s variables.","dados possuem %s observações de %s variáveis.",""
"if several use a comma ',' to separate them","se vários usarem uma vírgula ',' para separá-los","Automatically translated"
"lines, i.e.","linhas, ou seja,","Automatically translated"
"number of rows","numero de linhas","Automatically translated"
"proportion of rows","proporção de linhas","Automatically translated"
"rows","linhas","Automatically translated"
"then enter an expression before clicking on the button above to validate or on ","em seguida, insira uma expressão antes de clicar no botão acima para validar ou em","Automatically translated"
"to delete it.","para excluí-lo.","Automatically translated"
"Sort by count","Classificar por contagem","Automatically translated"
"Sort by levels","Classificar por níveis","Automatically translated"
================================================
FILE: inst/i18n/tr.csv
================================================
"label","translation","comment"
"% of the total","toplamın yüzdesi","Automatically translated"
"% of the total, i.e.","Toplamın yüzdesi, yani","Automatically translated"
"A shareable link, in that case first sheet will be read","Paylaşılabilir bir bağlantı, bu durumda ilk sayfa okunacak",""
"Add a label to data","Veriyi etiketle",""
"Add a row","satır ekle",""
"Apply changes","Değişiklikleri uygula",""
"Browse...","Gözat...",""
"Cancel","İptal",""
"Choose a name for the column to be created or modified,","Oluşturulacak veya değiştirilecek sütun için bir ad seçin,","Automatically translated"
"Choose a number of rows :","Bir dizi satır seçin:","Automatically translated"
"Choose a percentage :","Bir yüzde seçin:","Automatically translated"
"Click on a column name to add it to the expression:","İfadeye eklemek için bir sütun adına tıklayın:","Automatically translated"
"Click to delete","silmek için tıklayın",""
"Click to edit","Düzenlemek için tıkla",""
"Close","Kapat",""
"Close intervals on the right","Sağdaki yakın aralıklar","Automatically translated"
"Column added!","Sütun eklendi!","Automatically translated"
"Convert Numeric to Factor","Sayıyı Faktöre Dönüştür","Automatically translated"
"Copy & paste data","Veriyi kopyala & yapıştır",""
"Copy / Paste","Kopyala / Yapıştır",""
"Count","Saymak","Automatically translated"
"Create a new column","Yeni bir sütun oluştur","Automatically translated"
"Create a new variable otherwise replaces the one selected","Yeni bir değişken oluşturun, aksi halde seçilen değişkenin yerine geçer","Automatically translated"
"Create column","Sütun oluştur","Automatically translated"
"Create factor variable","Faktör değişkeni oluştur","Automatically translated"
"Data has %s observations and %s variables.","Veri %s gözlem ve %s değişken içeriyor.",""
"Data ready to be imported!","Veri içeri alınmak için hazır!",""
"Data successfully imported!","Veri başarıyla içeri alındı!",""
"Data successfully updated!","Veri başarıyla güncellendi!",""
"Data wasn't deleted","Veriler silinmedi","Automatically translated"
"Data wasn't updated","Veriler güncellenmedi","Automatically translated"
"Dataset validation:","Veri kümesi doğrulaması:","Automatically translated"
"Date format:","Tarih formatı:",""
"Date to use as origin to convert date/datetime:","Tarih/tarihsaat için başlangıç olarak kullanılacak tarih:",""
"Decimal separator:","Ondalık ayıracı:",""
"Delete","Silmek",""
"Do you want to delete the selected row ?","Seçilen satırı silmek istiyor musunuz?",""
"Encoding:","Kodlama:",""
"Enter URL to data:","Verilerin URL'sini girin:","Automatically translated"
"Enter a shareable link to a GoogleSheet:","GoogleSheet için paylaşılabilir bir bağlantı girin:",""
"Enter an expression to define new column:","Yeni sütunu tanımlamak için bir ifade girin:","Automatically translated"
"Environment","Ortam",""
"Error","Hata",""
"External file","Dış dosya",""
"Factor variable to reorder:","Yeniden sıralanacak faktör değişkeni:","Automatically translated"
"Failed","Başarısız",""
"First five rows are shown below:","İlk beş satır aşağıda gösterilmektedir:",""
"Googlesheets","Googlesheets",""
"Group calculation by:","Grup hesaplaması:","Automatically translated"
"Help","Yardım",""
"How to import data?","Veri alma nasıl yapılır?",""
"Import","İçeri al",""
"Import Google Spreadsheet","GoogleSheet verisi al",""
"Import Url","URL'yi içe aktar","Automatically translated"
"Import a dataset from an environment","Bir veri setini bir ortamdan al",""
"Import a file","Dosya al",""
"Import data","Veri al",""
"Imported data","İçe aktarılan veriler","Automatically translated"
"Include lowest value","En düşük değeri dahil et","Automatically translated"
"Information","Bilgi",""
"Item has been modified","Öğe değiştirildi",""
"Levels","Seviyeler","Automatically translated"
"List of data.frame...","Veri tablo listesi...",""
"Max:","Maksimum:","Automatically translated"
"Mean:","Anlam:","Automatically translated"
"Method:","Yöntem:","Automatically translated"
"Min:","Min:","Automatically translated"
"Missing values characters:","Eksik değer karakterleri:","Automatically translated"
"Missing:","Eksik:","Automatically translated"
"Most Common:","En Yaygın:","Automatically translated"
"New column name cannot be empty","Yeni sütun adı boş olamaz","Automatically translated"
"New column name:","Yeni sütun adı:","Automatically translated"
"No","Numara",""
"No data selected!","Veri seçilmedi!",""
"No data to display.","Gösterilecek veri yok.",""
"No data.frame here...","Burada veri tablosu yok...",""
"No file selected","Dosya seçilmedi",""
"No file selected:","Dosya seçilmedi:",""
"Not a data.frame","Bir data.frame değil","Automatically translated"
"Nothing pasted yet!","Henüz hiçbir şey yapıştırılmadı!",""
"Number of breaks:","Mola sayısı:","Automatically translated"
"Number of rows:","Satır sayısı:",""
"OK","Tamam",""
"Ooops","Ooops",""
"Paste data here:","Veriyi buraya yapıştır:",""
"Please copy and paste some data in the dialog box above.","Yukarıdaki pencereye birkaç veri kopyalayıp yapıştırın.",""
"Please fill in the required fields","Lütfen gerekli alanları doldurunuz",""
"Please paste a valid GoogleSheet link in the dialog box above.","Yukarıdaki pencereye geçerli bir GoogleSheet bağlantısı yapıştırın.",""
"Please paste a valid link in the dialog box above.","Lütfen yukarıdaki iletişim kutusuna geçerli bir bağlantı yapıştırın.","Automatically translated"
"Registered","Kayıtlı",""
"Required field","gerekli alan",""
"Row has been saved","Satır kaydedildi",""
"Row was not deleted","Satır silinmedi",""
"Rows to skip before reading data:","Verileri okumadan önce atlanacak satırlar:","Automatically translated"
"Sample data by :","Örnek veriler:","Automatically translated"
"Save","Kaydetmek",""
"Select","Seçme",""
"Select a data.frame:","Veri tablosu seçin:",""
"Select an environment in which to search:","Arama yapılacak ortamı seçin:",""
"Select environment","Ortam seç",""
"Select sheet to import:","İçeri almak için sayfa seçin:",""
"Some operations are not allowed","Bazı işlemlere izin verilmiyor","Automatically translated"
"Something went wrong...","Bir şeyler ters gitti...",""
"Sort count","Sıralama sayısı","Automatically translated"
"The URL that appear in your browser, in that case the current sheet will be read","Tarayıcınızda görünen URL, bu durumda geçerli sayfa okunacak",""
"The row has been deleted","Satır silinemiyor, platform yöneticisiyle iletişime geçin",""
"The row wasn't added to the data","Satır verilere eklenmedi","Automatically translated"
"URL","URL'si","Automatically translated"
"Unable to add the row, contact the platform administrator","Satır eklenemiyor, platform yöneticisiyle iletişime geçin",""
"Unable to delete the row, contact platform administrator","",""
"Unable to modify the item, contact the platform administrator","Öğe değiştirilemiyor, platform yöneticisiyle iletişime geçin",""
"Unique values:","Benzersiz değerler:","Automatically translated"
"Unique:","Eşsiz:","Automatically translated"
"Update","Güncelle",""
"Update & select variables","Güncelle & değişkenleri seç",""
"Update factor variable","Faktör değişkenini güncelle","Automatically translated"
"Update levels of a factor","Bir faktörün düzeylerini güncelleme","Automatically translated"
"Update row","Satırı güncelle",""
"Upload a file:","Dosya yükle:",""
"Use a data.frame from your environment or from the environment of a package.","Kendi ortamanızdan ya da bir paket ortamanından bir veri tablosu kullanın.",""
"Valid number of columns","Geçerli sütun sayısı","Automatically translated"
"Valid number of rows","Geçerli satır sayısı","Automatically translated"
"Validate","Doğrula",""
"Validation:","Doğrulama:",""
"Variable to cut:","Kesilecek değişken:","Automatically translated"
"View","Görüntüle",""
"Warning","Uyarı","Automatically translated"
"Yes","Evet",""
"You can either use:","Ya da şunu kullanın:",""
"You can import %s files","%s dosya içeri alabilirsiniz",""
"You can import from flat table format supported by","tarafından desteklenen düz tablo formatından içe aktarabilirsiniz.","Automatically translated"
"click to see data","veriyi görmek için tıklayın",""
"data has %s obs. of %s variables.","veri %s gözlem %s değişken içeriyor.",""
"if several use a comma ',' to separate them","birkaç kişi onları ayırmak için ',' virgülünü kullanıyorsa","Automatically translated"
"lines, i.e.","çizgiler, yani","Automatically translated"
"number of rows","satır sayısı","Automatically translated"
"proportion of rows","satırların oranı","Automatically translated"
"rows","satırlar","Automatically translated"
"then enter an expression before clicking on the button above to validate or on ","ardından doğrulamak için yukarıdaki düğmeye tıklamadan önce bir ifade girin veya","Automatically translated"
"to delete it.","silmek için.","Automatically translated"
"Sort by count","Sayıya göre sırala","Automatically translated"
"Sort by levels","Düzeylere göre sırala","Automatically translated"
================================================
FILE: man/create-column.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/create-column.R, R/update-factor.R
\name{create-column}
\alias{create-column}
\alias{create_column_ui}
\alias{create_column_server}
\alias{list_allowed_operations}
\alias{modal_create_column}
\alias{winbox_create_column}
\alias{winbox_update_factor}
\title{Create new column}
\usage{
create_column_ui(id)
create_column_server(
id,
data_r = reactive(NULL),
allowed_operations = list_allowed_operations()
)
list_allowed_operations()
modal_create_column(
id,
title = i18n("Create a new column"),
easyClose = TRUE,
size = "l",
footer = NULL
)
winbox_create_column(
id,
title = i18n("Create a new column"),
options = shinyWidgets::wbOptions(),
controls = shinyWidgets::wbControls()
)
winbox_update_factor(
id,
title = i18n("Update levels of a factor"),
options = shinyWidgets::wbOptions(),
controls = shinyWidgets::wbControls()
)
}
\arguments{
\item{id}{Module's ID.}
\item{data_r}{A \code{\link[shiny:reactive]{shiny::reactive()}} function returning a \code{data.frame}.}
\item{allowed_operations}{A \code{list} of allowed operations, see below for details.}
\item{title}{An optional title for the dialog.}
\item{easyClose}{If \code{TRUE}, the modal dialog can be dismissed by
clicking outside the dialog box, or be pressing the Escape key. If
\code{FALSE} (the default), the modal dialog can't be dismissed in those
ways; instead it must be dismissed by clicking on a \code{modalButton()}, or
from a call to \code{\link[shiny:removeModal]{removeModal()}} on the server.}
\item{size}{One of \code{"s"} for small, \code{"m"} (the default) for medium,
\code{"l"} for large, or \code{"xl"} for extra large. Note that \code{"xl"} only
works with Bootstrap 4 and above (to opt-in to Bootstrap 4+,
pass \code{\link[bslib:bs_theme]{bslib::bs_theme()}} to the \code{theme} argument of a page container
like \code{\link[shiny:fluidPage]{fluidPage()}}).}
\item{footer}{UI for footer. Use \code{NULL} for no footer.}
\item{options}{List of options, see \code{\link[shinyWidgets:wbOptions]{wbOptions()}}.}
\item{controls}{List of controls, see \code{\link[shinyWidgets:wbControls]{wbControls()}}.}
}
\value{
A \code{\link[shiny:reactive]{shiny::reactive()}} function returning the data.
}
\description{
This module allow to enter an expression to create a new column in a \code{data.frame}.
}
\note{
User can only use a subset of function: (, c, +, -, *, ^, \%\%, \%/\%, /, ==, >, <, !=, <=, >=, &, |, abs, sign, sqrt, ceiling, floor, trunc, cummax, cummin, cumprod, cumsum, exp, expm1, log, log10, log2, log1p, cos, cosh, sin, sinh, tan, tanh, acos, acosh, asin, asinh, atan, atanh, cospi, sinpi, tanpi, gamma, lgamma, digamma, trigamma, round, signif, max, min, range, prod, sum, any, all, pmin, pmax, mean, paste, paste0, substr, nchar, trimws, gsub, sub, grepl, ifelse, length, as.numeric, as.character, as.integer, as.Date, as.POSIXct, as.factor, factor.
You can add more operations using the \code{allowed_operations} argument, for example if you want to allow to use package lubridate, you can do:
\if{html}{\out{}}\preformatted{c(list_allowed_operations(), getNamespaceExports("lubridate"))
}\if{html}{\out{
}}
}
\examples{
library(shiny)
library(datamods)
library(reactable)
ui <- fluidPage(
theme = bslib::bs_theme(version = 5L, preset = "bootstrap"),
shinyWidgets::html_dependency_winbox(),
tags$h2("Create new column"),
fluidRow(
column(
width = 4,
create_column_ui("inline"),
actionButton("modal", "Or click here to open a modal to create a column"),
tags$br(), tags$br(),
actionButton("winbox", "Or click here to open a WinBox to create a column")
),
column(
width = 8,
reactableOutput(outputId = "table"),
verbatimTextOutput("code")
)
)
)
server <- function(input, output, session) {
rv <- reactiveValues(data = MASS::Cars93[, c(1, 3, 4, 5, 6, 10)])
# inline mode
data_inline_r <- create_column_server(
id = "inline",
data_r = reactive(rv$data)
)
observeEvent(data_inline_r(), rv$data <- data_inline_r())
# modal window mode
observeEvent(input$modal, modal_create_column("modal"))
data_modal_r <- create_column_server(
id = "modal",
data_r = reactive(rv$data)
)
observeEvent(data_modal_r(), rv$data <- data_modal_r())
# WinBox window mode
observeEvent(input$winbox, winbox_create_column("winbox"))
data_winbox_r <- create_column_server(
id = "winbox",
data_r = reactive(rv$data)
)
observeEvent(data_winbox_r(), rv$data <- data_winbox_r())
# Show result
output$table <- renderReactable({
data <- req(rv$data)
reactable(
data = data,
bordered = TRUE,
compact = TRUE,
striped = TRUE
)
})
output$code <- renderPrint({
attr(rv$data, "code")
})
}
if (interactive())
shinyApp(ui, server)
}
================================================
FILE: man/cut-variable.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/cut-variable.R
\name{cut-variable}
\alias{cut-variable}
\alias{cut_variable_ui}
\alias{cut_variable_server}
\alias{modal_cut_variable}
\alias{winbox_cut_variable}
\title{Module to Convert Numeric to Factor}
\usage{
cut_variable_ui(id)
cut_variable_server(id, data_r = reactive(NULL))
modal_cut_variable(
id,
title = i18n("Convert Numeric to Factor"),
easyClose = TRUE,
size = "l",
footer = NULL
)
winbox_cut_variable(
id,
title = i18n("Convert Numeric to Factor"),
options = shinyWidgets::wbOptions(),
controls = shinyWidgets::wbControls()
)
}
\arguments{
\item{id}{Module ID.}
\item{data_r}{A \code{\link[shiny:reactive]{shiny::reactive()}} function returning a \code{data.frame}.}
\item{title}{An optional title for the dialog.}
\item{easyClose}{If \code{TRUE}, the modal dialog can be dismissed by
clicking outside the dialog box, or be pressing the Escape key. If
\code{FALSE} (the default), the modal dialog can't be dismissed in those
ways; instead it must be dismissed by clicking on a \code{modalButton()}, or
from a call to \code{\link[shiny:removeModal]{removeModal()}} on the server.}
\item{size}{One of \code{"s"} for small, \code{"m"} (the default) for medium,
\code{"l"} for large, or \code{"xl"} for extra large. Note that \code{"xl"} only
works with Bootstrap 4 and above (to opt-in to Bootstrap 4+,
pass \code{\link[bslib:bs_theme]{bslib::bs_theme()}} to the \code{theme} argument of a page container
like \code{\link[shiny:fluidPage]{fluidPage()}}).}
\item{footer}{UI for footer. Use \code{NULL} for no footer.}
\item{options}{List of options, see \code{\link[shinyWidgets:wbOptions]{wbOptions()}}.}
\item{controls}{List of controls, see \code{\link[shinyWidgets:wbControls]{wbControls()}}.}
}
\value{
A \code{\link[shiny:reactive]{shiny::reactive()}} function returning the data.
}
\description{
This module contain an interface to cut a numeric into several intervals.
}
\examples{
library(shiny)
library(datamods)
library(reactable)
ui <- fluidPage(
theme = bslib::bs_theme(version = 5L, preset = "bootstrap"),
shinyWidgets::html_dependency_winbox(),
tags$h2("Convert Numeric to Factor"),
fluidRow(
column(
width = 6,
cut_variable_ui("inline"),
actionButton("modal", "Or click here to open a modal to cut a variable"),
tags$br(), tags$br(),
actionButton("winbox", "Or click here to open a WinBox to cut a variable")
),
column(
width = 6,
reactableOutput(outputId = "table"),
verbatimTextOutput("code")
)
)
)
server <- function(input, output, session) {
rv <- reactiveValues(data = MASS::Cars93[, c(1, 3, 4, 5, 6, 10)])
# inline mode
data_inline_r <- cut_variable_server(
id = "inline",
data_r = reactive(rv$data)
)
observeEvent(data_inline_r(), rv$data <- data_inline_r())
# modal window mode
observeEvent(input$modal, modal_cut_variable("modal"))
data_modal_r <- cut_variable_server(
id = "modal",
data_r = reactive(rv$data)
)
observeEvent(data_modal_r(), rv$data <- data_modal_r())
# WinBox window mode
observeEvent(input$winbox, winbox_cut_variable("winbox"))
data_winbox_r <- cut_variable_server(
id = "winbox",
data_r = reactive(rv$data)
)
observeEvent(data_winbox_r(), rv$data <- data_winbox_r())
# Show result
output$table <- renderReactable({
data <- req(rv$data)
reactable(
data = data,
bordered = TRUE,
compact = TRUE,
striped = TRUE
)
})
output$code <- renderPrint({
attr(rv$data, "code")
})
}
if (interactive())
shinyApp(ui, server)
}
================================================
FILE: man/demo_edit.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/data.R
\docType{data}
\name{demo_edit}
\alias{demo_edit}
\title{Customer Credit Card Information}
\format{
\subsection{\code{demo_edit}}{
A data frame with 20 rows and 6 columns:
\describe{
\item{name}{Customer name}
\item{job}{Customer job}
\item{credit_card_provider}{Credit card provider}
\item{credit_card_security_code}{Credit card security code}
\item{date_obtained}{Date of obtaining the credit card}
\item{contactless_card}{Contactless card}
}
}
}
\source{
\url{https://CRAN.R-project.org/package=charlatan}
}
\usage{
demo_edit
}
\description{
A subset of fake customer credit card information inspired by the \code{{charlatan}} package.
}
\keyword{datasets}
================================================
FILE: man/edit-data.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/edit-data.R
\name{edit-data}
\alias{edit-data}
\alias{edit_data_ui}
\alias{edit_data_server}
\title{Shiny module to interactively edit a \code{data.frame}}
\usage{
edit_data_ui(id)
edit_data_server(
id,
data_r = reactive(NULL),
add = TRUE,
update = TRUE,
delete = TRUE,
download_csv = TRUE,
download_excel = TRUE,
file_name_export = "data",
var_edit = NULL,
var_mandatory = NULL,
var_labels = NULL,
add_default_values = list(),
n_column = 1,
return_class = c("data.frame", "data.table", "tbl_df", "raw"),
reactable_options = NULL,
modal_size = c("m", "s", "l", "xl"),
modal_easy_close = TRUE,
callback_add = NULL,
callback_update = NULL,
callback_delete = NULL,
only_callback = FALSE,
use_notify = TRUE
)
}
\arguments{
\item{id}{Module ID}
\item{data_r}{data_r \code{reactive} function containing a \code{data.frame} to use in the module.}
\item{add}{\code{boolean}, if \code{TRUE}, allows you to add a row in the table via a button at the top right.}
\item{update}{\code{boolean}, if \code{TRUE}, allows you to modify a row of the table via a button located in the table on the row you want to edit.}
\item{delete}{\code{boolean}, if \code{TRUE}, allows a row to be deleted from the table via a button in the table.}
\item{download_csv}{if \code{TRUE}, allows to export the table in csv format via a download button.}
\item{download_excel}{if \code{TRUE}, allows to export the table in excel format via a download button.}
\item{file_name_export}{\code{character} that allows you to choose the export name of the downloaded file.}
\item{var_edit}{vector of \code{character} which allows to choose the names of the editable columns.}
\item{var_mandatory}{vector of \code{character} which allows to choose obligatory fields to fill.}
\item{var_labels}{named list, where names are colnames and values are labels to be used in edit modal.}
\item{add_default_values}{Default values to use for input control when adding new data, e.g. \code{list(my_var_text = "Default text to display")}.}
\item{n_column}{Number of column in the edit modal window, must be a number that divide 12 since it use Bootstrap grid system with \code{\link[shiny:column]{shiny::column()}}.}
\item{return_class}{Class of returned data: \code{data.frame}, \code{data.table}, \code{tbl_df} (tibble) or \code{raw}.}
\item{reactable_options}{Options passed to \code{\link[reactable:reactable]{reactable::reactable()}}.}
\item{modal_size}{\code{character} which allows to choose the size of the modalDialog. One of "s" for small, "m" (the default) for medium, "l" for large, or "xl" for extra large.}
\item{modal_easy_close}{\code{boolean} If TRUE, modalDialog can be dismissed by clicking outside the dialog box, or be pressing the Escape key. If FALSE (the default), modalDialog can't be dismissed in those ways; instead it must be dismissed by clicking on a modalButton(), or from a call to removeModal() on the server.}
\item{callback_add, callback_update, callback_delete}{Functions to be executed just before an action (add, update or delete) is performed on the data.
Functions used must be like \code{function(data, row) {...}} where :
\itemize{
\item \code{data} will be the data in the table at the moment the function is called
\item \code{row} will contain either a new row of data (add), an updated row (update) or the row that will be deleted (delete).
}
If the return value of a callback function is not truthy (see \code{\link[shiny:isTruthy]{shiny::isTruthy()}}) then the action is cancelled.}
\item{only_callback}{Only use callbacks, don't alter data within the module.}
\item{use_notify}{Display information or not to user through \code{\link[shinybusy:notify]{shinybusy::notify()}}.}
}
\value{
the edited \code{data.frame} in reactable format with the user modifications
}
\description{
The module generates different options to edit a \code{data.frame}: adding, deleting and modifying rows, exporting data (csv and excel), choosing editable columns, choosing mandatory columns.
This module returns the edited table with the user modifications.
}
\examples{
library(shiny)
library(datamods)
library(bslib)
library(reactable)
ui <- fluidPage(
theme = bs_theme(
version = 5
),
tags$h2("Edit data", align = "center"),
edit_data_ui(id = "id"),
verbatimTextOutput("result")
)
server <- function(input, output, session) {
edited_r <- edit_data_server(
id = "id",
data_r = reactive(demo_edit),
add = TRUE,
update = TRUE,
delete = TRUE,
download_csv = TRUE,
download_excel = TRUE,
file_name_export = "datas",
# var_edit = c("name", "job", "credit_card_provider", "credit_card_security_code"),
var_mandatory = c("name", "job"),
var_labels = list(
name = "Name",
credit_card_security_code = "Credit card security code",
date_obtained = "Date obtained",
contactless_card = "Contactless Card",
credit_card_provider = "Credit card provider"
),
add_default_values = list(
name = "Please enter your name here",
date_obtained = Sys.Date()
),
n_column = 2,
modal_size = "l",
modal_easy_close = TRUE,
reactable_options = list(
defaultColDef = colDef(filterable = TRUE),
selection = "single",
columns = list(
name = colDef(name = "Name", style = list(fontWeight = "bold")),
credit_card_security_code = colDef(name = "Credit card security code"),
date_obtained = colDef(name = "Date obtained", format = colFormat(date = TRUE)),
contactless_card = colDef(
name = "Contactless Card",
cell = htmlwidgets::JS(
"function(cellInfo) {
return cellInfo.value ? '\u2714\ufe0f Yes' : '\u274c No';
}"
)
),
credit_card_provider = colDef(
name = "Credit card provider",
style = htmlwidgets::JS(
"function(rowInfo) {
console.log(rowInfo);
var value = rowInfo.values['credit_card_provider'];
var color;
if (value == 'Mastercard') {
color = '#e06631';
} else if (value == 'VISA 16 digit') {
color = '#0c13cf';
} else if (value == 'American Express') {
color = '#4d8be8';
} else if (value == 'JCB 16 digit') {
color = '#23c45e';
} else {
color = '#777'
}
return {color: color, fontWeight: 'bold'}
}"
)
)
),
bordered = TRUE,
compact = TRUE,
searchable = TRUE,
highlight = TRUE
)
)
output$result <- renderPrint({
str(edited_r())
})
}
if (interactive())
shinyApp(ui, server)
}
================================================
FILE: man/filter-data.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/filter-data.R
\name{filter-data}
\alias{filter-data}
\alias{filter_data_ui}
\alias{filter_data_server}
\title{Shiny module to interactively filter a \code{data.frame}}
\usage{
filter_data_ui(id, show_nrow = TRUE, max_height = NULL)
filter_data_server(
id,
data = reactive(NULL),
vars = reactive(NULL),
name = reactive("data"),
defaults = reactive(NULL),
drop_ids = getOption("datamods.filter.drop_ids", default = TRUE),
widget_char = c("virtualSelect", "select", "picker"),
widget_num = c("slider", "range"),
widget_date = c("slider", "range"),
label_na = "NA",
value_na = TRUE
)
}
\arguments{
\item{id}{Module id. See \code{\link[shiny:moduleServer]{shiny::moduleServer()}}.}
\item{show_nrow}{Show number of filtered rows and total.}
\item{max_height}{Maximum height for filters panel, useful
if you have many variables to filter and limited space.}
\item{data}{\code{\link[shiny:reactive]{shiny::reactive()}} function returning a
\code{data.frame} to filter.}
\item{vars}{\code{\link[shiny:reactive]{shiny::reactive()}} function returning a
\code{character} vector of variables for which to add a filter.
If a named \code{list}, names are used as labels.}
\item{name}{\code{\link[shiny:reactive]{shiny::reactive()}} function returning a
\code{character} string representing \code{data} name, only used for code generated.}
\item{defaults}{\code{\link[shiny:reactive]{shiny::reactive()}} function returning a
named \code{list} of variable:value pairs which will be used to set the filters.}
\item{drop_ids}{Drop columns containing more than 90\% of unique values, or than 50 distinct values.
Use \code{FALSE} to disable or use \code{list(p = 0.9, n = 50)} to customize threshold values.}
\item{widget_char}{Widget to use for \code{character} variables: \code{\link[shinyWidgets:pickerInput]{shinyWidgets::pickerInput()}}
or \code{\link[shiny:selectInput]{shiny::selectInput()}} (default).}
\item{widget_num}{Widget to use for \code{numeric} variables: \code{\link[shinyWidgets:numericRangeInput]{shinyWidgets::numericRangeInput()}}
or \code{\link[shiny:sliderInput]{shiny::sliderInput()}} (default).}
\item{widget_date}{Widget to use for \code{date/time} variables: \code{\link[shiny:dateRangeInput]{shiny::dateRangeInput()}}
or \code{\link[shiny:sliderInput]{shiny::sliderInput()}} (default).}
\item{label_na}{Label for missing value widget.}
\item{value_na}{Default value for all NA's filters.}
}
\value{
\itemize{
\item UI: HTML tags that can be included in shiny's UI
\item Server: a \code{list} with four slots:
\itemize{
\item \strong{filtered}: a \code{reactive} function returning the data filtered.
\item \strong{code}: a \code{reactive} function returning the dplyr pipeline to filter data.
\item \strong{expr}: a \code{reactive} function returning an expression to filter data.
\item \strong{values}: a \code{reactive} function returning a named list of variables and filter values.
}
}
}
\description{
Module generate inputs to filter \code{data.frame} according column's type.
Code to reproduce the filter is returned as an expression with filtered data.
}
\examples{
library(shiny)
library(shinyWidgets)
library(datamods)
library(MASS)
# Add some NAs to mpg
mtcars_na <- mtcars
mtcars_na[] <- lapply(
X = mtcars_na,
FUN = function(x) {
x[sample.int(n = length(x), size = sample(5:10, 1))] <- NA
x
}
)
datetime <- data.frame(
date = seq(Sys.Date(), by = "day", length.out = 300),
datetime = seq(Sys.time(), by = "hour", length.out = 300),
num = sample.int(1e5, 300)
)
one_column_numeric <- data.frame(
var1 = rnorm(100)
)
ui <- fluidPage(
tags$h2("Filter data.frame"),
actionButton("saveFilterButton","Save Filter Values"),
actionButton("loadFilterButton","Load Filter Values"),
radioButtons(
inputId = "dataset",
label = "Data:",
choices = c(
"iris",
"mtcars",
"mtcars_na",
"Cars93",
"datetime",
"one_column_numeric"
),
inline = TRUE
),
fluidRow(
column(
width = 3,
filter_data_ui("filtering", max_height = "500px")
),
column(
width = 9,
progressBar(
id = "pbar", value = 100,
total = 100, display_pct = TRUE
),
reactable::reactableOutput(outputId = "table"),
tags$b("Code dplyr:"),
verbatimTextOutput(outputId = "code_dplyr"),
tags$b("Expression:"),
verbatimTextOutput(outputId = "code"),
tags$b("Filtered data:"),
verbatimTextOutput(outputId = "res_str")
)
)
)
server <- function(input, output, session) {
savedFilterValues <- reactiveVal()
data <- reactive({
get(input$dataset)
})
vars <- reactive({
if (identical(input$dataset, "mtcars")) {
setNames(as.list(names(mtcars)[1:5]), c(
"Miles/(US) gallon",
"Number of cylinders",
"Displacement (cu.in.)",
"Gross horsepower",
"Rear axle ratio"
))
} else {
NULL
}
})
observeEvent(input$saveFilterButton,{
savedFilterValues <<- res_filter$values()
},ignoreInit = T)
defaults <- reactive({
input$loadFilterButton
savedFilterValues
})
res_filter <- filter_data_server(
id = "filtering",
data = data,
name = reactive(input$dataset),
vars = vars,
defaults = defaults,
widget_num = "slider",
widget_date = "slider",
label_na = "Missing"
)
observeEvent(res_filter$filtered(), {
updateProgressBar(
session = session, id = "pbar",
value = nrow(res_filter$filtered()), total = nrow(data())
)
})
output$table <- reactable::renderReactable({
reactable::reactable(res_filter$filtered())
})
output$code_dplyr <- renderPrint({
res_filter$code()
})
output$code <- renderPrint({
res_filter$expr()
})
output$res_str <- renderPrint({
str(res_filter$filtered())
})
}
if (interactive())
shinyApp(ui, server)
}
================================================
FILE: man/get_data_packages.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/import-globalenv.R
\name{get_data_packages}
\alias{get_data_packages}
\title{Get packages containing datasets}
\usage{
get_data_packages()
}
\value{
a character vector of packages names
}
\description{
Get packages containing datasets
}
\examples{
if (interactive()) {
get_data_packages()
}
}
================================================
FILE: man/i18n.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/i18n.R
\name{i18n}
\alias{i18n}
\alias{i18n_translations}
\alias{set_i18n}
\title{Internationalization}
\usage{
i18n(x, translations = i18n_translations())
i18n_translations(package = packageName(parent.frame(2)))
set_i18n(value, packages = c("datamods", "esquisse"))
}
\arguments{
\item{x}{Label to translate.}
\item{translations}{Either a \code{list} or a \code{data.frame} with translations.}
\item{package}{Name of the package where the function is called, use \code{NULL} outside a package.
It will retrieve option \code{"i18n."} (or \code{"i18n"} if no package) to returns appropriate labels.}
\item{value}{Value to set for translation. Can be:
\itemize{
\item single \code{character} to use a supported language (\code{"fr"}, \code{"mk"}, \code{"al"}, \code{"pt"} for esquisse and datamods packages).
\item a \code{list} with labels as names and translations as values.
\item a \code{data.frame} with 2 column: \code{label} & \code{translation}.
\item path to a CSV file with same structure as for \code{data.frame} above.
}}
\item{packages}{Name of packages for which to set i18n, default to esquisse and datamods}
}
\value{
\code{i18n()} returns a \code{character}, \code{i18n_translations()} returns a \code{list} or a \code{data.frame}.
}
\description{
Simple mechanism to translate labels in a Shiny application.
}
\examples{
library(datamods)
# Use with an objet
my.translations <- list(
"Hello" = "Bonjour"
)
i18n("Hello", my.translations)
# Use with options()
options("i18n" = list(
"Hello" = "Bonjour"
))
i18n("Hello")
# With a package
options("datamods.i18n" = "fr")
i18n("Browse...", translations = i18n_translations("datamods"))
# If you call i18n() from within a function of your package
# you don't need second argument, e.g.:
# i18n("Browse...")
}
================================================
FILE: man/import-copypaste.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/import-copypaste.R
\name{import-copypaste}
\alias{import-copypaste}
\alias{import_copypaste_ui}
\alias{import_copypaste_server}
\title{Import data with copy & paste}
\usage{
import_copypaste_ui(id, title = TRUE, name_field = TRUE)
import_copypaste_server(
id,
btn_show_data = TRUE,
show_data_in = c("popup", "modal"),
trigger_return = c("button", "change"),
return_class = c("data.frame", "data.table", "tbl_df", "raw"),
reset = reactive(NULL),
fread_args = list()
)
}
\arguments{
\item{id}{Module's ID.}
\item{title}{Module's title, if \code{TRUE} use the default title,
use \code{NULL} for no title or a \code{shiny.tag} for a custom one.}
\item{name_field}{Show or not a field to add a name to data (that is returned server-side).}
\item{btn_show_data}{Display or not a button to display data in a modal window if import is successful.}
\item{show_data_in}{Where to display data: in a \code{"popup"} or in a \code{"modal"} window.}
\item{trigger_return}{When to update selected data:
\code{"button"} (when user click on button) or
\code{"change"} (each time user select a dataset in the list).}
\item{return_class}{Class of returned data: \code{data.frame}, \code{data.table}, \code{tbl_df} (tibble) or \code{raw}.}
\item{reset}{A \code{reactive} function that when triggered resets the data.}
\item{fread_args}{\code{list} of additional arguments to pass to \code{\link[data.table:fread]{data.table::fread()}} when reading data.}
}
\value{
\itemize{
\item UI: HTML tags that can be included in shiny's UI
\item Server: a \code{list} with three slots:
\itemize{
\item \strong{status}: a \code{reactive} function returning the status: \code{NULL}, \code{error} or \code{success}.
\item \strong{name}: a \code{reactive} function returning the name of the imported data as \code{character}.
\item \strong{data}: a \code{reactive} function returning the imported \code{data.frame}.
}
}
}
\description{
Let the user copy data from Excel or text file then paste it into a text area to import it.
}
\examples{
library(shiny)
library(datamods)
ui <- fluidPage(
tags$h3("Import data with copy & paste"),
fluidRow(
column(
width = 4,
import_copypaste_ui("myid")
),
column(
width = 8,
tags$b("Import status:"),
verbatimTextOutput(outputId = "status"),
tags$b("Name:"),
verbatimTextOutput(outputId = "name"),
tags$b("Data:"),
verbatimTextOutput(outputId = "data")
)
)
)
server <- function(input, output, session) {
imported <- import_copypaste_server("myid")
output$status <- renderPrint({
imported$status()
})
output$name <- renderPrint({
imported$name()
})
output$data <- renderPrint({
imported$data()
})
}
if (interactive())
shinyApp(ui, server)
}
================================================
FILE: man/import-file.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/import-file.R
\name{import-file}
\alias{import-file}
\alias{import_file_ui}
\alias{import_file_server}
\title{Import data from a file}
\usage{
import_file_ui(
id,
title = TRUE,
preview_data = TRUE,
file_extensions = c(".csv", ".txt", ".xls", ".xlsx", ".rds", ".fst", ".sas7bdat",
".sav"),
layout_params = c("dropdown", "inline")
)
import_file_server(
id,
btn_show_data = TRUE,
show_data_in = "winbox",
trigger_return = c("button", "change"),
return_class = c("data.frame", "data.table", "tbl_df", "raw"),
reset = reactive(NULL),
read_fns = list()
)
}
\arguments{
\item{id}{Module's ID.}
\item{title}{Module's title, if \code{TRUE} use the default title,
use \code{NULL} for no title or a \code{shiny.tag} for a custom one.}
\item{preview_data}{Show or not a preview of the data under the file input.}
\item{file_extensions}{File extensions accepted by \code{\link[shiny:fileInput]{shiny::fileInput()}}, can also be MIME type.}
\item{layout_params}{How to display import parameters : in a dropdown button or inline below file input.}
\item{btn_show_data}{Display or not a button to display data in a modal window if import is successful.}
\item{show_data_in}{Where to display data: in a \code{"popup"} or in a \code{"modal"} window.}
\item{trigger_return}{When to update selected data:
\code{"button"} (when user click on button) or
\code{"change"} (each time user select a dataset in the list).}
\item{return_class}{Class of returned data: \code{data.frame}, \code{data.table}, \code{tbl_df} (tibble) or \code{raw}.}
\item{reset}{A \code{reactive} function that when triggered resets the data.}
\item{read_fns}{Named list with custom function(s) to read data:
\itemize{
\item the name must be the extension of the files to which the function will be applied
\item the value must be a function that can have 5 arguments (you can ignore some of them, but you have to use the same names),
passed by user through the interface:
\itemize{
\item \code{file}: path to the file
\item \code{sheet}: for Excel files, sheet to read
\item \code{skip}: number of row to skip
\item \code{dec}: decimal separator
\item \code{encoding}: file encoding
\item \code{na.strings}: character(s) to interpret as missing values.
}
}}
}
\value{
\itemize{
\item UI: HTML tags that can be included in shiny's UI
\item Server: a \code{list} with three slots:
\itemize{
\item \strong{status}: a \code{reactive} function returning the status: \code{NULL}, \code{error} or \code{success}.
\item \strong{name}: a \code{reactive} function returning the name of the imported data as \code{character}.
\item \strong{data}: a \code{reactive} function returning the imported \code{data.frame}.
}
}
}
\description{
Let user upload a file and import data
}
\examples{
library(shiny)
library(datamods)
ui <- fluidPage(
# theme = bslib::bs_theme(version = 5L),
# theme = bslib::bs_theme(version = 5L, preset = "bootstrap"),
tags$h3("Import data from a file"),
fluidRow(
column(
width = 4,
import_file_ui(
id = "myid",
file_extensions = c(".csv", ".txt", ".xls", ".xlsx", ".json"),
layout_params = "inline" # or "dropdown"
)
),
column(
width = 8,
tags$b("Import status:"),
verbatimTextOutput(outputId = "status"),
tags$b("Name:"),
verbatimTextOutput(outputId = "name"),
tags$b("Code:"),
verbatimTextOutput(outputId = "code"),
tags$b("Data:"),
verbatimTextOutput(outputId = "data")
)
)
)
server <- function(input, output, session) {
imported <- import_file_server(
id = "myid",
# Custom functions to read data
read_fns = list(
xls = function(file, sheet, skip, encoding) {
readxl::read_xls(path = file, sheet = sheet, skip = skip)
},
json = function(file) {
jsonlite::read_json(file, simplifyVector = TRUE)
}
),
show_data_in = "modal"
)
output$status <- renderPrint({
imported$status()
})
output$name <- renderPrint({
imported$name()
})
output$code <- renderPrint({
imported$code()
})
output$data <- renderPrint({
imported$data()
})
}
if (interactive())
shinyApp(ui, server)
}
================================================
FILE: man/import-globalenv.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/import-globalenv.R
\name{import-globalenv}
\alias{import-globalenv}
\alias{import_globalenv_ui}
\alias{import_globalenv_server}
\title{Import data from an Environment}
\usage{
import_globalenv_ui(
id,
globalenv = TRUE,
packages = get_data_packages(),
title = TRUE
)
import_globalenv_server(
id,
btn_show_data = TRUE,
show_data_in = c("popup", "modal"),
trigger_return = c("button", "change"),
return_class = c("data.frame", "data.table", "tbl_df", "raw"),
reset = reactive(NULL)
)
}
\arguments{
\item{id}{Module's ID.}
\item{globalenv}{Search for data in Global environment.}
\item{packages}{Name of packages in which to search data.}
\item{title}{Module's title, if \code{TRUE} use the default title,
use \code{NULL} for no title or a \code{shiny.tag} for a custom one.}
\item{btn_show_data}{Display or not a button to display data in a modal window if import is successful.}
\item{show_data_in}{Where to display data: in a \code{"popup"} or in a \code{"modal"} window.}
\item{trigger_return}{When to update selected data:
\code{"button"} (when user click on button) or
\code{"change"} (each time user select a dataset in the list).}
\item{return_class}{Class of returned data: \code{data.frame}, \code{data.table}, \code{tbl_df} (tibble) or \code{raw}.}
\item{reset}{A \code{reactive} function that when triggered resets the data.}
}
\value{
\itemize{
\item UI: HTML tags that can be included in shiny's UI
\item Server: a \code{list} with three slots:
\itemize{
\item \strong{status}: a \code{reactive} function returning the status: \code{NULL}, \code{error} or \code{success}.
\item \strong{name}: a \code{reactive} function returning the name of the imported data as \code{character}.
\item \strong{data}: a \code{reactive} function returning the imported \code{data.frame}.
}
}
}
\description{
Let the user select a dataset from its own environment or from a package's environment.
}
\examples{
if (interactive()) {
library(shiny)
library(datamods)
# Create some data.frames
my_df <- data.frame(
variable1 = sample(letters, 20, TRUE),
variable2 = sample(1:100, 20, TRUE)
)
results_analysis <- data.frame(
id = sample(letters, 20, TRUE),
measure = sample(1:100, 20, TRUE),
response = sample(1:100, 20, TRUE)
)
# Application
ui <- fluidPage(
fluidRow(
column(
width = 4,
import_globalenv_ui("myid")
),
column(
width = 8,
tags$b("Import status:"),
verbatimTextOutput(outputId = "status"),
tags$b("Name:"),
verbatimTextOutput(outputId = "name"),
tags$b("Data:"),
verbatimTextOutput(outputId = "data")
)
)
)
server <- function(input, output, session) {
imported <- import_globalenv_server("myid")
output$status <- renderPrint({
imported$status()
})
output$name <- renderPrint({
imported$name()
})
output$data <- renderPrint({
imported$data()
})
}
shinyApp(ui, server)
}
}
================================================
FILE: man/import-googlesheets.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/import-googlesheets.R
\name{import-googlesheets}
\alias{import-googlesheets}
\alias{import_googlesheets_ui}
\alias{import_googlesheets_server}
\title{Import data from Googlesheet}
\usage{
import_googlesheets_ui(id, title = TRUE)
import_googlesheets_server(
id,
btn_show_data = TRUE,
show_data_in = c("popup", "modal"),
trigger_return = c("button", "change"),
return_class = c("data.frame", "data.table", "tbl_df", "raw"),
reset = reactive(NULL)
)
}
\arguments{
\item{id}{Module's ID.}
\item{title}{Module's title, if \code{TRUE} use the default title,
use \code{NULL} for no title or a \code{shiny.tag} for a custom one.}
\item{btn_show_data}{Display or not a button to display data in a modal window if import is successful.}
\item{show_data_in}{Where to display data: in a \code{"popup"} or in a \code{"modal"} window.}
\item{trigger_return}{When to update selected data:
\code{"button"} (when user click on button) or
\code{"change"} (each time user select a dataset in the list).}
\item{return_class}{Class of returned data: \code{data.frame}, \code{data.table}, \code{tbl_df} (tibble) or \code{raw}.}
\item{reset}{A \code{reactive} function that when triggered resets the data.}
}
\value{
\itemize{
\item UI: HTML tags that can be included in shiny's UI
\item Server: a \code{list} with three slots:
\itemize{
\item \strong{status}: a \code{reactive} function returning the status: \code{NULL}, \code{error} or \code{success}.
\item \strong{name}: a \code{reactive} function returning the name of the imported data as \code{character}.
\item \strong{data}: a \code{reactive} function returning the imported \code{data.frame}.
}
}
}
\description{
Let user paste link to a Google sheet then import the data.
}
\examples{
library(shiny)
library(datamods)
ui <- fluidPage(
tags$h3("Import data from Googlesheets"),
fluidRow(
column(
width = 4,
import_googlesheets_ui("myid")
),
column(
width = 8,
tags$b("Import status:"),
verbatimTextOutput(outputId = "status"),
tags$b("Name:"),
verbatimTextOutput(outputId = "name"),
tags$b("Data:"),
verbatimTextOutput(outputId = "data")
)
)
)
server <- function(input, output, session) {
imported <- import_googlesheets_server("myid")
output$status <- renderPrint({
imported$status()
})
output$name <- renderPrint({
imported$name()
})
output$data <- renderPrint({
imported$data()
})
}
if (interactive())
shinyApp(ui, server)
}
================================================
FILE: man/import-modal.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/import-modal.R
\name{import-modal}
\alias{import-modal}
\alias{import_ui}
\alias{import_server}
\alias{import_modal}
\title{Import from all sources}
\usage{
import_ui(
id,
from = c("env", "file", "copypaste", "googlesheets", "url"),
file_extensions = c(".csv", ".txt", ".xls", ".xlsx", ".rds", ".fst", ".sas7bdat",
".sav")
)
import_server(
id,
validation_opts = NULL,
allowed_status = c("OK", "Failed", "Error"),
return_class = c("data.frame", "data.table", "tbl_df", "raw"),
read_fns = list()
)
import_modal(
id,
from,
title = i18n("Import data"),
size = "l",
file_extensions = c(".csv", ".txt", ".xls", ".xlsx", ".rds", ".fst", ".sas7bdat",
".sav")
)
}
\arguments{
\item{id}{Module's id}
\item{from}{The import_ui & server to use, i.e. the method.
There are 5 options to choose from. ("env", "file", "copypaste", "googlesheets", "url")}
\item{file_extensions}{File extensions accepted by \code{\link[shiny:fileInput]{shiny::fileInput()}}, can also be MIME type.}
\item{validation_opts}{\code{list} of arguments passed to [validation_server().}
\item{allowed_status}{Vector of statuses allowed to confirm dataset imported,
if you want that all validation rules are successful before importing data use \code{allowed_status = "OK"}.}
\item{return_class}{Class of returned data: \code{data.frame}, \code{data.table}, \code{tbl_df} (tibble) or \code{raw}.}
\item{read_fns}{Named list with custom function(s) to read data:
\itemize{
\item the name must be the extension of the files to which the function will be applied
\item the value must be a function that can have 5 arguments (you can ignore some of them, but you have to use the same names),
passed by user through the interface:
\itemize{
\item \code{file}: path to the file
\item \code{sheet}: for Excel files, sheet to read
\item \code{skip}: number of row to skip
\item \code{dec}: decimal separator
\item \code{encoding}: file encoding
\item \code{na.strings}: character(s) to interpret as missing values.
}
}}
\item{title}{Modal window title.}
\item{size}{Modal window size, default to \code{"l"} (large).}
}
\value{
\itemize{
\item UI: HTML tags that can be included in shiny's UI
\item Server: a \code{list} with three slots:
\itemize{
\item \strong{status}: a \code{reactive} function returning the status: \code{NULL}, \code{error} or \code{success}.
\item \strong{name}: a \code{reactive} function returning the name of the imported data as \code{character}.
\item \strong{data}: a \code{reactive} function returning the imported \code{data.frame}.
}
}
}
\description{
Wrap all import modules into one, can be displayed inline or in a modal window..
}
\examples{
library(shiny)
library(datamods)
ui <- fluidPage(
# Try with different Bootstrap version
theme = bslib::bs_theme(version = 5, preset = "bootstrap"),
fluidRow(
column(
width = 4,
checkboxGroupInput(
inputId = "from",
label = "From",
choices = c("env", "file", "copypaste", "googlesheets", "url"),
selected = c("file", "copypaste")
),
actionButton("launch_modal", "Launch modal window")
),
column(
width = 8,
tags$b("Imported data:"),
verbatimTextOutput(outputId = "name"),
verbatimTextOutput(outputId = "data"),
verbatimTextOutput(outputId = "str_data")
)
)
)
server <- function(input, output, session) {
observeEvent(input$launch_modal, {
req(input$from)
import_modal(
id = "myid",
from = input$from,
title = "Import data to be used in application"
)
})
imported <- import_server("myid", return_class = "tbl_df")
output$name <- renderPrint({
req(imported$name())
imported$name()
})
output$data <- renderPrint({
req(imported$data())
imported$data()
})
output$str_data <- renderPrint({
req(imported$data())
str(imported$data())
})
}
if (interactive())
shinyApp(ui, server)
}
================================================
FILE: man/import-url.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/import-url.R
\name{import-url}
\alias{import-url}
\alias{import_url_ui}
\alias{import_url_server}
\title{Import data from a URL}
\usage{
import_url_ui(id, title = TRUE)
import_url_server(
id,
btn_show_data = TRUE,
show_data_in = c("popup", "modal"),
trigger_return = c("button", "change"),
return_class = c("data.frame", "data.table", "tbl_df", "raw"),
reset = reactive(NULL)
)
}
\arguments{
\item{id}{Module's ID.}
\item{title}{Module's title, if \code{TRUE} use the default title,
use \code{NULL} for no title or a \code{shiny.tag} for a custom one.}
\item{btn_show_data}{Display or not a button to display data in a modal window if import is successful.}
\item{show_data_in}{Where to display data: in a \code{"popup"} or in a \code{"modal"} window.}
\item{trigger_return}{When to update selected data:
\code{"button"} (when user click on button) or
\code{"change"} (each time user select a dataset in the list).}
\item{return_class}{Class of returned data: \code{data.frame}, \code{data.table}, \code{tbl_df} (tibble) or \code{raw}.}
\item{reset}{A \code{reactive} function that when triggered resets the data.}
}
\value{
\itemize{
\item UI: HTML tags that can be included in shiny's UI
\item Server: a \code{list} with three slots:
\itemize{
\item \strong{status}: a \code{reactive} function returning the status: \code{NULL}, \code{error} or \code{success}.
\item \strong{name}: a \code{reactive} function returning the name of the imported data as \code{character}.
\item \strong{data}: a \code{reactive} function returning the imported \code{data.frame}.
}
}
}
\description{
Let user paste link to a JSON then import the data.
}
\examples{
library(shiny)
library(datamods)
ui <- fluidPage(
tags$h3("Import data from URL"),
fluidRow(
column(
width = 4,
import_url_ui("myid")
),
column(
width = 8,
tags$b("Import status:"),
verbatimTextOutput(outputId = "status"),
tags$b("Name:"),
verbatimTextOutput(outputId = "name"),
tags$b("Data:"),
verbatimTextOutput(outputId = "data")
)
)
)
server <- function(input, output, session) {
imported <- import_url_server(
"myid",
btn_show_data = FALSE,
return_class = "raw"
)
output$status <- renderPrint({
imported$status()
})
output$name <- renderPrint({
imported$name()
})
output$data <- renderPrint({
imported$data()
})
}
if (interactive())
shinyApp(ui, server)
}
================================================
FILE: man/list_pkg_data.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/import-globalenv.R
\name{list_pkg_data}
\alias{list_pkg_data}
\title{List dataset contained in a package}
\usage{
list_pkg_data(pkg)
}
\arguments{
\item{pkg}{Name of the package, must be installed.}
}
\value{
a \code{character} vector or \code{NULL}.
}
\description{
List dataset contained in a package
}
\examples{
list_pkg_data("ggplot2")
}
================================================
FILE: man/module-sample.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/sample-data.R
\name{module-sample}
\alias{module-sample}
\alias{sample_ui}
\alias{sample_server}
\title{Shiny module to interactively sample a \code{data.frame}}
\usage{
sample_ui(id)
sample_server(id, data_r = reactive(NULL))
}
\arguments{
\item{id}{Module id. See \code{\link[shiny:moduleServer]{shiny::moduleServer()}}.}
\item{data_r}{\code{reactive} containing a \code{data.frame} to use in the module.}
}
\value{
\itemize{
\item UI: HTML tags that can be included in shiny's UI
\item Server: a \code{reactive} fgunction with the sampled data.
}
}
\description{
Allow to take a sample of \code{data.frame} for a given number or proportion of rows to keep.
}
\examples{
library(shiny)
library(datamods)
library(reactable)
ui <- fluidPage(
tags$h2("Sampling"),
fluidRow(
column(
width = 3,
sample_ui("myID")
),
column(
width = 9,
reactableOutput("table")
)
)
)
server <- function(input, output, session) {
result_sample <- sample_server("myID", reactive(iris))
output$table <- renderReactable({
table_sample <- reactable(
data = result_sample(),
defaultColDef = colDef(
align = "center"
),
borderless = TRUE,
highlight = TRUE,
striped = TRUE
)
return(table_sample)
})
}
if (interactive())
shinyApp(ui, server)
}
================================================
FILE: man/select-group.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/select-group.R
\name{select-group}
\alias{select-group}
\alias{select_group_ui}
\alias{select_group_server}
\title{Select Group Input Module}
\usage{
select_group_ui(
id,
params,
label = NULL,
btn_reset_label = "Reset filters",
inline = TRUE,
vs_args = list()
)
select_group_server(id, data_r, vars_r, selected_r = reactive(list()))
}
\arguments{
\item{id}{Module's id.}
\item{params}{A list of parameters passed to each \code{\link[shinyWidgets:virtualSelectInput]{shinyWidgets::virtualSelectInput()}},
you can use :
\itemize{
\item \code{inputId}: mandatory, must correspond to variable name.
\item \code{label}: Display label for the control.
\item \code{placeholder}: Text to show when no options selected.
}}
\item{label}{Character, global label on top of all labels.}
\item{btn_reset_label}{Character, reset button label. If \code{NULL} no button is added.}
\item{inline}{If \code{TRUE} (the default),
select menus are horizontally positioned, otherwise vertically.}
\item{vs_args}{Arguments passed to all \code{\link[shinyWidgets:virtualSelectInput]{shinyWidgets::virtualSelectInput()}} created.}
\item{data_r}{Either a \code{\link[=data.frame]{data.frame()}} or a \code{\link[shiny:reactive]{shiny::reactive()}}
function returning a \code{data.frame} (do not use parentheses).}
\item{vars_r}{character, columns to use to create filters,
must correspond to variables listed in \code{params}. Can be a
\code{\link[shiny:reactive]{shiny::reactive()}} function, but values must be included in the initial ones (in \code{params}).}
\item{selected_r}{\code{\link[shiny:reactive]{shiny::reactive()}} function returning a named list with selected values to set.}
}
\value{
A \code{\link[shiny:reactive]{shiny::reactive()}} function containing data filtered with an attribute \code{inputs} containing a named list of selected inputs.
}
\description{
Group of mutually dependent select menus for filtering \code{data.frame}'s columns (like in Excel).
}
\examples{
# Default -----------------------------------------------------------------
library(shiny)
library(datamods)
library(shinyWidgets)
ui <- fluidPage(
# theme = bslib::bs_theme(version = 5L),
fluidRow(
column(
width = 10, offset = 1,
tags$h3("Filter data with select group module"),
shinyWidgets::panel(
select_group_ui(
id = "my-filters",
params = list(
list(inputId = "Manufacturer", label = "Manufacturer:"),
list(inputId = "Type", label = "Type:"),
list(inputId = "AirBags", label = "AirBags:"),
list(inputId = "DriveTrain", label = "DriveTrain:")
), vs_args = list(disableSelectAll = FALSE)
),
status = "primary"
),
reactable::reactableOutput(outputId = "table"),
tags$b("Inputs values:"),
verbatimTextOutput("inputs")
)
)
)
server <- function(input, output, session) {
res_mod <- select_group_server(
id = "my-filters",
data = reactive(MASS::Cars93),
vars = reactive(c("Manufacturer", "Type", "AirBags", "DriveTrain"))
)
output$table <- reactable::renderReactable({
reactable::reactable(res_mod())
})
output$inputs <- renderPrint({
attr(res_mod(), "inputs")
})
}
if (interactive())
shinyApp(ui, server)
# Selected value --------------------------------------------------------------------
library(shiny)
library(datamods)
ui <- fluidPage(
select_group_ui(
id = "my-filters",
params = list(
list(inputId = "Manufacturer", label = "Manufacturer:"),
list(inputId = "Type", label = "Type:")
),
vs_args = list(
disableSelectAll = FALSE
)
),
actionButton("set_sel", "Set Manufacturer=Acura"),
verbatimTextOutput("res")
)
server <- function(input, output, session) {
# We use a reactiveValue so that it can be updated
rv <- reactiveValues(selected = list(Manufacturer = "Audi")) # for init
res_r <- select_group_server(
id = "my-filters",
data = reactive(MASS::Cars93),
vars = reactive(c("Manufacturer", "Type")),
selected_r = reactive(rv$selected)
)
output$res <- renderPrint({
res_r()
})
observeEvent(input$set_sel, {
rv$selected <- list(Manufacturer = "Acura")
})
}
if (interactive())
shinyApp(ui, server)
}
================================================
FILE: man/show_data.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/show_data.R
\name{show_data}
\alias{show_data}
\title{Display a table in a window}
\usage{
show_data(
data,
title = NULL,
options = NULL,
show_classes = TRUE,
type = c("popup", "modal", "winbox"),
width = "65\%",
...,
session = shiny::getDefaultReactiveDomain()
)
}
\arguments{
\item{data}{a data object (either a \code{matrix} or a \code{data.frame}).}
\item{title}{Title to be displayed in window.}
\item{options}{Arguments passed to \code{\link[toastui:datagrid]{toastui::datagrid()}}.}
\item{show_classes}{Show variables classes under variables names in table header.}
\item{type}{Display table in a pop-up with \code{\link[shinyWidgets:sweetalert]{shinyWidgets::show_alert()}},
in modal window with \code{\link[shiny:showModal]{shiny::showModal()}} or in a WinBox window with \code{\link[shinyWidgets:WinBox]{shinyWidgets::WinBox()}}.}
\item{width}{Width of the window, only used if \code{type = "popup"} or \code{type = "winbox"}.}
\item{...}{Additional options, such as \code{wbOptions = wbOptions()} or \code{wbControls = wbControls()}.}
\item{session}{The \code{session} object passed to function given to
\code{shinyServer}.}
}
\value{
No value.
}
\description{
Display a table in a window
}
\note{
If you use \code{type = "winbox"}, you'll need to use \code{shinyWidgets::html_dependency_winbox()} somewhere in your UI.
}
\examples{
library(shiny)
library(datamods)
ui <- fluidPage(
theme = bslib::bs_theme(version = 5L),
shinyWidgets::html_dependency_winbox(),
actionButton(
inputId = "show1",
label = "Show data in popup",
icon = icon("eye")
),
actionButton(
inputId = "show2",
label = "Show data in modal",
icon = icon("eye")
),
actionButton(
inputId = "show3",
label = "Show data without classes",
icon = icon("eye")
),
actionButton(
inputId = "show4",
label = "Show data in Winbox",
icon = icon("eye")
)
)
server <- function(input, output, session) {
observeEvent(input$show1, {
show_data(MASS::Cars93, title = "MASS::Cars93 dataset", type = "popup")
})
observeEvent(input$show2, {
show_data(MASS::Cars93, title = "MASS::Cars93 dataset", type = "modal")
})
observeEvent(input$show3, {
show_data(
data = MASS::Cars93,
title = "MASS::Cars93 dataset",
show_classes = FALSE,
options = list(pagination = 10),
type = "modal"
)
})
observeEvent(input$show4, {
show_data(
MASS::Cars93,
title = "MASS::Cars93 dataset",
type = "winbox",
wbOptions = shinyWidgets::wbOptions(background = "forestgreen")
)
})
}
if (interactive())
shinyApp(ui, server)
}
================================================
FILE: man/update-factor.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/update-factor.R
\name{update-factor}
\alias{update-factor}
\alias{update_factor_ui}
\alias{update_factor_server}
\alias{modal_update_factor}
\title{Module to Reorder the Levels of a Factor Variable}
\usage{
update_factor_ui(id)
update_factor_server(id, data_r = reactive(NULL))
modal_update_factor(
id,
title = i18n("Update levels of a factor"),
easyClose = TRUE,
size = "l",
footer = NULL
)
}
\arguments{
\item{id}{Module ID.}
\item{data_r}{A \code{\link[shiny:reactive]{shiny::reactive()}} function returning a \code{data.frame}.}
\item{title}{An optional title for the dialog.}
\item{easyClose}{If \code{TRUE}, the modal dialog can be dismissed by
clicking outside the dialog box, or be pressing the Escape key. If
\code{FALSE} (the default), the modal dialog can't be dismissed in those
ways; instead it must be dismissed by clicking on a \code{modalButton()}, or
from a call to \code{\link[shiny:removeModal]{removeModal()}} on the server.}
\item{size}{One of \code{"s"} for small, \code{"m"} (the default) for medium,
\code{"l"} for large, or \code{"xl"} for extra large. Note that \code{"xl"} only
works with Bootstrap 4 and above (to opt-in to Bootstrap 4+,
pass \code{\link[bslib:bs_theme]{bslib::bs_theme()}} to the \code{theme} argument of a page container
like \code{\link[shiny:fluidPage]{fluidPage()}}).}
\item{footer}{UI for footer. Use \code{NULL} for no footer.}
}
\value{
A \code{\link[shiny:reactive]{shiny::reactive()}} function returning the data.
}
\description{
This module contain an interface to reorder the levels of a factor variable.
}
\examples{
library(shiny)
library(datamods)
library(ggplot2)
ui <- fluidPage(
theme = bslib::bs_theme(version = 5L, preset = "bootstrap"),
shinyWidgets::html_dependency_winbox(),
tags$h2("Reorder the Levels of a Factor"),
fluidRow(
column(
width = 6,
update_factor_ui("id"),
actionButton("modal", "Or click here to open a modal to update factor's level"),
tags$br(), tags$br(),
actionButton("winbox", "Or click here to open a WinBox to create a column")
),
column(
width = 6,
selectInput(
"var",
label = "Variable to plot:",
choices = NULL
),
plotOutput("plot"),
verbatimTextOutput("res")
)
)
)
server <- function(input, output, session) {
rv <- reactiveValues(data = MASS::Cars93[c(1, 2, 3, 9, 10, 11, 16, 26, 27)])
observe(
updateSelectInput(inputId = "var", choices = names(rv$data))
)
# Inline mode
data_inline_r <- update_factor_server(
id = "id",
data_r = reactive(rv$data)
)
observeEvent(data_inline_r(), rv$data <- data_inline_r())
# modal window mode
observeEvent(input$modal, modal_update_factor("modal"))
data_modal_r <- update_factor_server(
id = "modal",
data_r = reactive(rv$data)
)
observeEvent(data_modal_r(), {
shiny::removeModal()
rv$data <- data_modal_r()
})
# winbox mode
observeEvent(input$winbox, winbox_update_factor("winbox"))
data_winbox_r <- update_factor_server(
id = "winbox",
data_r = reactive(rv$data)
)
observeEvent(data_winbox_r(), rv$data <- data_winbox_r())
# Plot results
output$plot <- renderPlot({
req(input$var, rv$data)
ggplot(rv$data) +
aes(x = !!sym(input$var)) +
geom_bar()
})
# Show results
output$res <- renderPrint({
data <- req(rv$data)
str(data)
})
}
if (interactive())
shinyApp(ui, server)
}
================================================
FILE: man/update-variables.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/update-variables.R
\name{update-variables}
\alias{update-variables}
\alias{update_variables_ui}
\alias{update_variables_server}
\title{Select, rename and convert variables}
\usage{
update_variables_ui(id, title = TRUE)
update_variables_server(
id,
data,
height = NULL,
return_data_on_init = FALSE,
try_silent = FALSE
)
}
\arguments{
\item{id}{Module's ID}
\item{title}{Module's title, if \code{TRUE} use the default title,
use \code{NULL} for no title or a \code{shiny.tag} for a custom one.}
\item{data}{a \code{data.frame} or a \code{reactive} function returning a \code{data.frame}.}
\item{height}{Height for the table.}
\item{return_data_on_init}{Return initial data when module is called.}
\item{try_silent}{logical: should the report of error messages be suppressed?}
}
\value{
A \code{\link[shiny:reactive]{shiny::reactive()}} function returning the updated data.
}
\description{
Select, rename and convert variables
}
\examples{
library(shiny)
library(datamods)
testdata <- data.frame(
date_as_char = as.character(Sys.Date() + 0:9),
date_as_num = as.numeric(Sys.Date() + 0:9),
datetime_as_char = as.character(Sys.time() + 0:9 * 3600*24),
datetime_as_num = as.numeric(Sys.time() + 0:9 * 3600*24),
num_as_char = as.character(1:10),
char = month.name[1:10],
char_na = c("A", "A", "B", NA, "B", "A", NA, "B", "A", "B"),
stringsAsFactors = FALSE
)
ui <- fluidPage(
theme = bslib::bs_theme(version = 5L, preset = "bootstrap"),
tags$h3("Select, rename and convert variables"),
fluidRow(
column(
width = 6,
# radioButtons()
update_variables_ui("vars")
),
column(
width = 6,
tags$b("original data:"),
verbatimTextOutput("original"),
verbatimTextOutput("original_str"),
tags$b("Modified data:"),
verbatimTextOutput("modified"),
verbatimTextOutput("modified_str")
)
)
)
server <- function(input, output, session) {
updated_data <- update_variables_server(
id = "vars",
data = reactive(testdata),
return_data_on_init = FALSE
)
output$original <- renderPrint({
testdata
})
output$original_str <- renderPrint({
str(testdata)
})
output$modified <- renderPrint({
updated_data()
})
output$modified_str <- renderPrint({
str(updated_data())
})
}
if (interactive())
shinyApp(ui, server)
}
================================================
FILE: man/validation.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/validation.R
\name{validation_ui}
\alias{validation_ui}
\alias{validation_server}
\title{Validation module}
\usage{
validation_ui(id, display = c("dropdown", "inline"), max_height = NULL, ...)
validation_server(
id,
data,
n_row = NULL,
n_col = NULL,
n_row_label = i18n("Valid number of rows"),
n_col_label = i18n("Valid number of columns"),
btn_label = i18n("Dataset validation:"),
rules = NULL,
bs_version = 3
)
}
\arguments{
\item{id}{Module's ID.}
\item{display}{Display validation results in a dropdown menu
by clicking on a button or display results directly in interface.}
\item{max_height}{Maximum height for validation results element, useful if you have many rules.}
\item{...}{Arguments passed to \code{actionButton} or \code{uiOutput} depending on display mode,
you cannot use \code{inputId}/\code{outputId}, \code{label} or \code{icon} (button only).}
\item{data}{a \code{reactive} function returning a \code{data.frame}.}
\item{n_row, n_col}{A one-sided formula to check number of rows and columns respectively, see below for examples.}
\item{n_row_label, n_col_label}{Text to be displayed with the result of the check for number of rows/columns.}
\item{btn_label}{Label for the dropdown button, will be followed by validation result.}
\item{rules}{An object of class \code{validator} created with \code{validate::validator}.}
\item{bs_version}{Bootstrap version used, it may affect rendering, especially status badges.}
}
\value{
\itemize{
\item UI: HTML tags that can be included in shiny's UI
\item Server: a \code{list} with two slots:
\itemize{
\item \strong{status}: a \code{reactive} function returning the best status available between \code{"OK"}, \code{"Failed"} or \code{"Error"}.
\item \strong{details}: a \code{reactive} function returning a \code{list} with validation details.
}
}
}
\description{
Check that a dataset respect some validation expectations.
}
\examples{
library(datamods)
library(shiny)
if (requireNamespace("validate")) {
library(validate)
# Define some rules to be applied to data
myrules <- validator(
is.character(Manufacturer) | is.factor(Manufacturer),
is.numeric(Price),
Price > 12, # we should use 0 for testing positivity, but that's for the example
!is.na(Luggage.room),
in_range(Cylinders, min = 4, max = 8),
Man.trans.avail \%in\% c("Yes", "No")
)
# Add some labels
label(myrules) <- c(
"Variable Manufacturer must be character",
"Variable Price must be numeric",
"Variable Price must be strictly positive",
"Luggage.room must not contain any missing values",
"Cylinders must be between 4 and 8",
"Man.trans.avail must be 'Yes' or 'No'"
)
# you can also add a description()
ui <- fluidPage(
tags$h2("Validation"),
fluidRow(
column(
width = 4,
radioButtons(
inputId = "dataset",
label = "Choose dataset:",
choices = c("mtcars", "MASS::Cars93")
),
tags$p("Dropdown example:"),
validation_ui("validation1"),
tags$br(),
tags$p("Inline example:"),
validation_ui("validation2", display = "inline")
),
column(
width = 8,
tags$b("Status:"),
verbatimTextOutput("status"),
tags$b("Details:"),
verbatimTextOutput("details")
)
)
)
server <- function(input, output, session) {
dataset <- reactive({
if (input$dataset == "mtcars") {
mtcars
} else {
MASS::Cars93
}
})
results <- validation_server(
id = "validation1",
data = dataset,
n_row = ~ . > 20, # more than 20 rows
n_col = ~ . >= 3, # at least 3 columns
rules = myrules
)
validation_server(
id = "validation2",
data = dataset,
n_row = ~ . > 20, # more than 20 rows
n_col = ~ . >= 3, # at least 3 columns
rules = myrules
)
output$status <- renderPrint(results$status())
output$details <- renderPrint(results$details())
}
if (interactive())
shinyApp(ui, server)
}
}
================================================
FILE: man-roxygen/module-import.R
================================================
#' @return
#' * UI: HTML tags that can be included in shiny's UI
#' * Server: a `list` with three slots:
#' + **status**: a `reactive` function returning the status: `NULL`, `error` or `success`.
#' + **name**: a `reactive` function returning the name of the imported data as `character`.
#' + **data**: a `reactive` function returning the imported `data.frame`.
================================================
FILE: tests/testthat/test-edit-data.R
================================================
test_that("edit_data_ui works", {
expect_is(edit_data_ui("ID"), "shiny.tag.list")
})
test_that("table_display works", {
mydata <- iris
mydata <- as.data.table(mydata)
mydata[, .datamods_edit_update := as.character(seq_len(.N))]
mydata[, .datamods_edit_delete := as.character(seq_len(.N))]
mydata[, .datamods_id := seq_len(.N)]
mydata <- table_display(mydata, colnames = NULL)
expect_is(mydata, "reactable")
expect_is(mydata, "htmlwidget")
expect_length(mydata$x$tag$attribs$columns, 8)
expect_equal(length(mydata$x$tag$attribs$columns), 8)
})
test_that("col_def_update works", {
col_def_update <- col_def_update()
expect_is(col_def_update, "colDef")
expect_equal(col_def_update$name, "Update")
expect_named(col_def_update, c('name', 'sortable', 'filterable', 'html', 'width'))
})
test_that("col_def_delete works", {
col_def_delete <- col_def_delete()
expect_is(col_def_delete, "colDef")
expect_equal(col_def_delete$name, "Delete")
expect_named(col_def_delete, c('name', 'sortable', 'filterable', 'html', 'width'))
})
test_that("btn_update works", {
expect_is(btn_update("input"), "function")
expect_is(btn_update("input")(1), "html")
expect_is(btn_update("input")(1), "character")
})
test_that("btn_delete works", {
expect_is(btn_delete("input"), "function")
expect_is(btn_delete("input")(1), "html")
expect_is(btn_delete("input")(1), "character")
})
test_that("confirmation_window works", {
expect_is(confirmation_window(inputId = "input", title = "titre"), "shiny.tag")
})
================================================
FILE: tests/testthat/test-filter-data.R
================================================
test_that("filter_data_ui works", {
expect_is(filter_data_ui("ID"), "shiny.tag.list")
})
test_that("create_filters works", {
filters <- create_filters(iris, session = list(ns = identity))
expect_length(filters, 3)
expect_named(filters, c("ui", "filters_id", "filters_na_id"))
expect_is(filters$ui, "shiny.tag")
expect_length(filters$filters_id, ncol(iris))
expect_equal(length(filters$ui$children[[1]]), length(filters$filters_id))
expect_equal(length(filters$filters_id), length(filters$filters_na_id))
})
test_that("create_filters with options works", {
filters <- create_filters(iris, vars = names(iris)[1:3], widget_num = "range", session = list(ns = identity))
expect_length(filters, 3)
expect_named(filters, c("ui", "filters_id", "filters_na_id"))
expect_is(filters$ui, "shiny.tag")
expect_length(filters$filters_id, 3)
expect_equal(length(filters$ui$children[[1]]), length(filters$filters_id))
expect_equal(length(filters$filters_id), length(filters$filters_na_id))
})
test_that("create_filters with dates and ids works", {
mydata <- data.frame(
date = seq(as.Date("2021-01-01"), by = "1 month", length.out = 12),
name = month.name,
num = rep(c(1, 2), each = 6)
)
filters <- create_filters(mydata, session = list(ns = identity))
expect_length(filters, 3)
expect_named(filters, c("ui", "filters_id", "filters_na_id"))
expect_is(filters$ui, "shiny.tag")
expect_length(filters$filters_id, 2)
expect_equal(length(filters$ui$children[[1]]), length(filters$filters_id))
expect_equal(length(filters$filters_id), length(filters$filters_na_id))
})
test_that("create_filters with dates and ids works (bis)", {
mydata <- data.frame(
date = seq(as.Date("2021-01-01"), by = "1 month", length.out = 12),
name = month.name,
num = rep(c(1, 2), each = 6)
)
filters <- create_filters(mydata, widget_date = "range", session = list(ns = identity))
expect_length(filters, 3)
expect_named(filters, c("ui", "filters_id", "filters_na_id"))
expect_is(filters$ui, "shiny.tag")
expect_length(filters$filters_id, 2)
expect_equal(length(filters$ui$children[[1]]), length(filters$filters_id))
expect_equal(length(filters$filters_id), length(filters$filters_na_id))
})
test_that("make_expr_filter works", {
filter_inputs <- lapply(
X = iris,
FUN = function(x) {
sort(sample(unique(x), 2))
}
)
filter_nas <- lapply(
X = iris,
FUN = function(x) {
sample(c(TRUE, FALSE), 2)
}
)
filters <- make_expr_filter(
filters = filter_inputs,
filters_na = filter_nas,
data = iris,
data_name = "iris"
)
expect_length(filters, 2)
expect_named(filters, c("expr_dplyr", "expr"))
expect_is(filters$expr_dplyr, "call")
expect_is(filters$expr, "call")
})
test_that("make_expr_filter with dates works", {
mydata <- data.frame(
date = seq(as.Date("2021-01-01"), by = "1 month", length.out = 12),
name = month.name,
num = rep(c(1, 2), each = 6)
)
filter_inputs <- lapply(
X = mydata,
FUN = function(x) {
sort(sample(unique(x), 2))
}
)
filter_nas <- lapply(
X = mydata,
FUN = function(x) {
sample(c(TRUE, FALSE), 2)
}
)
filters <- make_expr_filter(
filters = filter_inputs,
filters_na = filter_nas,
data = mydata,
data_name = "mydata"
)
expect_length(filters, 2)
expect_named(filters, c("expr_dplyr", "expr"))
expect_is(filters$expr_dplyr, "call")
expect_is(filters$expr, "call")
})
================================================
FILE: tests/testthat/test-i18n.R
================================================
test_that("i18n works if option not set", {
options("datamods.i18n" = NULL)
label <- "something"
expect_identical(i18n(label), label)
})
test_that("i18n works with translation argument", {
options("datamods.i18n" = NULL)
label <- "something"
translation <- "quelque chose"
l <- list(translation)
names(l) <- label
expect_identical(i18n(label, l), translation)
})
test_that("i18n works with option set", {
options("datamods.i18n" = NULL)
label <- "something"
translation <- "quelque chose"
l <- list(translation)
names(l) <- label
options("i18n" = l)
expect_identical(i18n(label, i18n_translations(NULL)), translation)
})
test_that("i18n works with list", {
label <- "something"
translation <- "quelque chose"
l <- list(translation)
names(l) <- label
options("datamods.i18n" = l)
expect_identical(i18n_test(label), translation)
expect_warning(i18n_test("label"))
})
test_that("i18n works with data.frame", {
label <- "something"
translation <- "quelque chose"
options("datamods.i18n" = data.frame(
label = label,
translation = translation,
stringsAsFactors = FALSE
))
expect_identical(i18n_test(label), translation)
expect_warning(i18n_test("label"))
})
test_that("i18n works with file", {
options("datamods.i18n" = system.file(
"i18n", "fr.csv", package = "datamods"
))
expect_identical(i18n_test("Help"), "Aide")
})
test_that("i18n works with supported language", {
options("datamods.i18n" = "fr")
expect_identical(i18n_test("Help"), "Aide")
options("datamods.i18n" = "mk")
expect_type(i18n_test("Help"), "character")
options("datamods.i18n" = "pt")
expect_type(i18n_test("Help"), "character")
options("datamods.i18n" = "al")
expect_type(i18n_test("Help"), "character")
})
test_that("i18n dont work if no list, no data.frame, no file", {
options("datamods.i18n" = Sys.Date())
on.exit(options("datamods.i18n" = NULL))
label <- "something"
expect_error(i18n_test(label))
})
================================================
FILE: tests/testthat/test-import-copypaste.R
================================================
test_that("import_copypaste_ui works", {
expect_is(import_copypaste_ui("ID"), "shiny.tag")
})
test_that("import_copypaste_server works", {
shiny::testServer(import_copypaste_server, {
session$setInputs(data_pasted = 0) #to bypass ignoreInit = TRUE
session$setInputs(
data_pasted =
"x y z
1 2 3",
confirm = 0
)
expect_is(imported_rv$data, "data.frame")
expect_is(session$getReturned()$data(), "data.frame")
})
})
================================================
FILE: tests/testthat/test-import-file.R
================================================
test_that("import_file_ui works", {
expect_is(import_file_ui("ID"), "shiny.tag")
})
test_that("import_file_server works", {
shiny::testServer(import_file_server, {
session$setInputs(sheet = 0) #to bypass ignoreInit = TRUE
session$setInputs(
file = data.frame(
datapath = system.file("extdata", "mtcars.csv", package = "datamods"),
stringsAsFactors = FALSE
),
sheet = 0,
skip_rows = 0,
confirm = 0,
dec = ".",
encoding = "UTF-8",
na_label = ",NA"
)
expect_is(imported_rv$data, "data.frame")
expect_is(session$getReturned()$data(), "data.frame")
})
})
================================================
FILE: tests/testthat/test-import-globalenv.R
================================================
test_that("import_globalenv_ui works", {
expect_is(import_globalenv_ui("ID"), "shiny.tag")
})
test_that("import_globalenv_server works", {
data(mtcars)
shiny::testServer(import_globalenv_server, {
session$setInputs(data = 0) #to bypass ignoreInit = TRUE
session$setInputs(
data = "mtcars",
confirm = 0
)
expect_equal(imported_rv$name, input$data)
expect_equal(session$getReturned()$name(), input$data)
expect_is(imported_rv$data, "data.frame")
expect_is(session$getReturned()$data(), "data.frame")
session$setInputs(env = "datasets")
session$setInputs(data = "faithful", confirm = 1)
expect_is(session$getReturned()$data(), "data.frame")
expect_equivalent(session$getReturned()$data(), faithful)
})
})
test_that("get_dimensions works", {
expect_null(get_dimensions(NULL))
mydata <- mtcars
mydata2 <- mtcars
expect_is(get_dimensions("mydata"), "character")
expect_length(get_dimensions(c("mydata", "mydata2")), 2)
mylist <- list(a = 1)
expect_identical(unname(get_dimensions("mylist")), "Not a data.frame")
})
test_that("list_pkg_data works", {
expect_null(list_pkg_data("not.a.package"))
expect_is(list_pkg_data("datasets"), "character")
})
================================================
FILE: tests/testthat/test-import-googlesheets.R
================================================
test_that("import_googlesheets_ui works", {
expect_is(import_googlesheets_ui("ID"), "shiny.tag")
})
test_that("import_googlesheets_server works", {
testthat::skip_on_cran()
testthat::skip_if_offline()
shiny::testServer(import_googlesheets_server, {
session$setInputs(link = 0) #to bypass ignoreInit = TRUE
session$setInputs(
link = "https://docs.google.com/spreadsheets/d/1U6Cf_qEOhiR9AZqTqS3mbMF3zt2db48ZP5v3rkrAEJY/edit?usp=sharing",
confirm = 0
)
expect_is(imported_rv$data, "data.frame")
expect_is(session$getReturned()$data(), "data.frame")
})
})
================================================
FILE: tests/testthat/test-import-modal.R
================================================
test_that("import_ui works", {
expect_is(import_ui("ID"), "shiny.tag")
})
test_that("import_server works", {
shiny::testServer(import_server, args = list(return_class = "data.table"), {
data(mtcars)
session$env$data_rv$data = mtcars
session$env$data_rv$name = "mtcars"
session$setInputs(confirm = 1)
expect_is(session$getReturned()$data(), "data.table")
expect_equal(session$getReturned()$name(), "mtcars")
})
})
================================================
FILE: tests/testthat/test-import-url.R
================================================
test_that("import_url_ui works", {
expect_is(import_url_ui("ID"), "shiny.tag")
})
test_that("import_url_server works with json", {
testthat::skip_on_cran()
testthat::skip_if_offline()
shiny::testServer(import_url_server, {
session$setInputs(link = 0) #to bypass ignoreInit = TRUE
session$setInputs(
link = "https://raw.githubusercontent.com/dreamRs/datamods/master/inst/extdata/mtcars.json",
confirm = 0
)
expect_is(imported_rv$data, "data.frame")
expect_is(session$getReturned()$data(), "data.frame")
})
})
test_that("import_url_server works with csv", {
testthat::skip_on_cran()
testthat::skip_if_offline()
shiny::testServer(import_url_server, {
session$setInputs(link = 0) #to bypass ignoreInit = TRUE
session$setInputs(
link = "https://raw.githubusercontent.com/dreamRs/datamods/master/inst/extdata/mtcars.csv",
confirm = 0
)
expect_is(imported_rv$data, "data.frame")
expect_is(session$getReturned()$data(), "data.frame")
})
})
test_that("import_url_server works with shortened URL", {
testthat::skip_on_cran()
testthat::skip_if_offline()
shiny::testServer(import_url_server, {
session$setInputs(link = 0) #to bypass ignoreInit = TRUE
session$setInputs(
link = "https://tinyurl.com/datamodsjson",
confirm = 0
)
expect_is(imported_rv$data, "data.frame")
expect_is(session$getReturned()$data(), "data.frame")
})
})
================================================
FILE: tests/testthat/test-onLoad.R
================================================
test_that("onLoad works", {
.onLoad()
x <- shiny::resourcePaths()
expect_true("datamods" %in% names(x))
})
================================================
FILE: tests/testthat/test-update-variables.R
================================================
test_that("update_variables_ui works", {
expect_is(update_variables_ui("ID"), "shiny.tag")
})
# test_that("update_variables_server works", {
# data(mtcars)
# shiny::testServer(update_variables_server, args = list(data = mtcars), {
# tok <- token$x
# selection <- as.list(rep(TRUE, ncol(mtcars)))
# names(selection) <- paste("selection", tok, pad0(seq_along(mtcars)), sep = "-")
#
# name <- as.list(names(mtcars))
# names(name) <- paste("name", tok, pad0(seq_along(mtcars)), sep = "-")
#
# class_toset <- as.list(rep("numeric", ncol(mtcars)))
# names(class_toset) <- paste("class_to_set", tok, pad0(seq_along(mtcars)), sep = "-")
#
# do.call(session$setInputs, selection)
# do.call(session$setInputs, name)
# do.call(session$setInputs, class_toset)
#
# session$setInputs(validate = 1)
#
# # print(session$getReturned()())
# expect_is(session$getReturned()(), "data.frame")
# expect_equal(session$getReturned()(), mtcars)
# })
# })
test_that("get_classes works", {
expect_is(get_classes(mtcars), "character")
expect_length(get_classes(mtcars), ncol(mtcars))
})
test_that("get_classes works", {
expect_is(get_n_unique(mtcars), "integer")
expect_length(get_n_unique(mtcars), ncol(mtcars))
})
test_that("pad0 works", {
expect_is(pad0(c(1, 15, 150, NA)), "character")
expect_length(pad0(c(1, 15, 150, NA)), 4)
})
test_that("summary_vars works", {
expect_is(summary_vars(mtcars), "data.frame")
expect_identical(nrow(summary_vars(mtcars)), ncol(mtcars))
})
test_that("update_variables_datagrid works", {
variables <- summary_vars(iris)
dt <- update_variables_datagrid(variables)
expect_is(dt, "htmlwidget")
})
test_that("convert_to works", {
dat <- data.frame(
v1 = month.name,
v2 = month.abb,
v3 = 1:12,
v4 = as.numeric(Sys.Date() + 0:11),
v5 = as.character(Sys.Date() + 0:11),
v6 = as.factor(c("a", "a", "b", "a", "b", "a", "a", "b", "a", "b", "b", "a")),
v7 = as.character(11:22),
stringsAsFactors = FALSE
)
expect_is(
convert_to(dat, "v3", "character")$v3,
"character"
)
expect_is(
convert_to(dat, "v6", "character")$v6,
"character"
)
expect_is(
convert_to(dat, "v7", "numeric")$v7,
"numeric"
)
expect_is(
convert_to(dat, "v4", "date", origin = "1970-01-01")$v4,
"Date"
)
expect_is(
convert_to(dat, "v5", "date")$v5,
"Date"
)
})
test_that("get_vars_to_convert works", {
# 2 variables to convert
new_classes <- list(
"Sepal.Length" = "numeric",
"Sepal.Width" = "numeric",
"Petal.Length" = "character",
"Petal.Width" = "numeric",
"Species" = "character"
)
res <- get_vars_to_convert(summary_vars(iris), new_classes)
expect_is(res, "data.frame")
expect_identical(nrow(res), 2L)
# No changes
new_classes <- list(
"Sepal.Length" = "numeric",
"Sepal.Width" = "numeric",
"Petal.Length" = "numeric",
"Petal.Width" = "numeric",
"Species" = "factor"
)
res <- get_vars_to_convert(summary_vars(iris), new_classes)
expect_is(res, "data.frame")
expect_identical(nrow(res), 0L)
new_classes <- list(
"mpg" = "character",
"cyl" = "numeric",
"disp" = "character",
"hp" = "numeric",
"drat" = "character",
"wt" = "character",
"qsec" = "numeric",
"vs" = "character",
"am" = "numeric",
"gear" = "character",
"carb" = "integer"
)
res <- get_vars_to_convert(summary_vars(mtcars), new_classes)
expect_is(res, "data.frame")
expect_identical(nrow(res), 7L)
})
================================================
FILE: tests/testthat/test-validation.R
================================================
test_that("validation_ui works", {
expect_is(validation_ui("ID"), "shiny.tag.list")
expect_is(validation_ui("ID", display = "inline"), "shiny.tag.list")
})
# test_that("validation_server works", {
# rv <- shiny::reactiveVal(cars)
# shiny::testServer(
# validation_server,
# args = list(
# data = rv,
# n_row = ~ . > 20,
# n_col = ~ . >= 3,
# rules = validate::validator(
# speed >= 0
# , dist >= 0
# , speed/dist <= 1.5
# )
# ), {
# rv(cars)
# expect_is(valid_ui$x, "shiny.tag")
# expect_is(valid_rv$status, "character")
# }
# )
# })
================================================
FILE: tests/testthat.R
================================================
library(testthat)
library(datamods)
test_check("datamods")
================================================
FILE: vignettes/.gitignore
================================================
*.html
*.R
================================================
FILE: vignettes/datamods.Rmd
================================================
---
title: "Getting started with datamods"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Getting started with datamods}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
eval = FALSE
)
```
```{r setup}
library(datamods)
```
The {datamods} package contains modules to work with data in Shiny application, currently the following modules are implemented :
* Import modules : import data from various sources
* Update table structure: select columns to keep, rename variable and convert from a class to anoter (e.g. numeric to character)
* Filter data : interactively filter a `data.frame`
* Validate : check that data respect some expectations (with [package {validate}](https://cran.r-project.org/package=validate))
* Sample data: interactively sample a `data.frame`.
## Import
### From environment
Imports data from the user's global environment or a package environment to retrieve included in it.
It searches for data sets in the global environment and lets the user choose the data to use.
```r
# UI
import_globalenv_ui("myid")
# Server
imported <- import_globalenv_server("myid")
```
### From file
Imports data from an external file. The file can be of any format, csv, xlsx, tsv etc.. Import is performed by package [rio](https://github.com/gesistsa/rio).
In case of Excel files, it gives an option to choose the sheet.
```r
# UI
import_file_ui("myid")
# Server
imported <- import_file_server("myid")
```
### From clipboard
Imports data via copy/paste. Simply copy and paste data from any source.
```r
# UI
import_copypaste_ui("myid")
# Server
imported <- import_copypaste_server("myid")
```
### From Googlesheet
Imports data from a Googlesheet. Use the shareable link to read data.
```r
# UI
import_googlesheets_ui("myid")
# Server
imported <- import_googlesheets_server("myid")
```
### From URL
Imports data from a URL. Only flat data in any format supported by [package rio](https://CRAN.R-project.org/package=rio/vignettes/rio.html#Supported_file_formats).
```r
# UI
import_url_ui("myid")
# Server
imported <- import_url_server("myid")
```
### Usage
All modules are used in the same way in a Shiny application, here is an example:
```r
library(shiny)
library(datamods)
ui <- fluidPage(
tags$h3("Import data with copy & paste"),
fluidRow(
column(
width = 4,
import_copypaste_ui("myid")
),
column(
width = 8,
tags$b("Imported data:"),
verbatimTextOutput(outputId = "status"),
verbatimTextOutput(outputId = "data")
)
)
)
server <- function(input, output, session) {
imported <- import_copypaste_server("myid")
output$status <- renderPrint({
imported$status()
})
output$data <- renderPrint({
imported$data()
})
}
shinyApp(ui, server)
```
All modules have the same return value server-side, a `list` with three slots:
* **status**: a `reactive` function returning the status: `NULL`, `error` or `success`.
* **name**: a `reactive` function returning the name of the imported data as `character`.
* **data**: a `reactive` function returning the imported `data.frame`.
### Modal Window
All modules can be launched at once in a modal window:
Launch the modal server-side with:
```r
observeEvent(input$launch_modal, {
import_modal(
id = "myid",
title = "Import data to be used in application"
)
})
```
See `?import_modal` for a complete example.
## Update Modules
This module allow to dynamically select, rename and convert variables of a dataset.
Some options for converting to date and numeric are available in a dropdown menu.
Return value of the module is a `reactive` function with the update data.
## Validate
When importing data into an application it can be useful to check that data respect some expectations: number of rows/columns, existence of a variable, ... This module allow to validate rules defined with package [validate](https://github.com/data-cleaning/validate).
```r
# UI
validation_ui("validation", display = "inline")
# Server
results <- validation_server(
id = "validation",
data = dataset,
n_row = ~ . > 20, # more than 20 rows
n_col = ~ . >= 3, # at least 3 columns
rules = myrules
)
# Rules are defined as follow:
myrules <- validator(
is.character(Manufacturer) | is.factor(Manufacturer),
is.numeric(Price),
Price > 12, # we should use 0 for testing positivity, but that's for the example
!is.na(Luggage.room),
in_range(Cylinders, min = 4, max = 8),
Man.trans.avail %in% c("Yes", "No")
)
# Add some labels
label(myrules) <- c(
"Variable Manufacturer must be character",
"Variable Price must be numeric",
"Variable Price must be strictly positive",
"Luggage.room must not contain any missing values",
"Cylinders must be between 4 and 8",
"Man.trans.avail must be 'Yes' or 'No'"
)
# you can also add a description()
```
Validation results can be displayed in a dropdown menu (above left) or inline where the module is called.
The return value server-side is a list with the following items:
* **status**: a reactive function returning the best status available between "OK", "Failed" or "Error".
* **details**: a reactive function returning a list with validation details.
## Filter
Interactively filter a `data.frame` and generate code to reproduce filters applied:
```r
# UI
filter_data_ui("filtering", max_height = "500px")
# Server
res_filter <- filter_data_server(
id = "filtering",
data = reactive(mtcars),
name = reactive("mtcars"),
vars = reactive(names(mtcars)),
widget_num = "slider",
widget_date = "slider",
label_na = "Missing"
)
```
You can select variables for which to create a filter and choose widgets used to create the UI filter.
The return value server-side is a list with the following items:
* **filtered**: a `reactive` function returning the data filtered.
* **code**: a `reactive` function returning the dplyr pipeline to filter data.
* **expr**: a `reactive` function returning an expression to filter data.
## Sample
Interactively sample a `data.frame` to keep only part of the data, depending on the number or proportion of rows to keep.
```r
# UI
sample_ui("myID")
# Server
result_sample <- sample_server("myID", reactive(iris))
```
## Edit
Interactively edit a `data.frame`, this module also allow to :
* **adding**, **deleting** and **modifying** rows
* choosing **editable columns** and choosing **mandatory columns**
* **exporting data** (csv and Excel)
```r
# UI
edit_data_ui(id = "id")
# Server
res_edited <- edit_data_server(
id = "id",
data_r = reactive(demo_edit),
add = TRUE,
update = TRUE,
delete = TRUE,
download_csv = TRUE,
download_excel = TRUE,
file_name_export = "datas",
var_edit = c("name", "job", "credit_card_provider", "credit_card_security_code"),
var_mandatory = c("name", "job")
)
```
This module returns the edited table with the user modifications.
See ?demo_edit to see the data created for this data edit example.
================================================
FILE: vignettes/i18n.Rmd
================================================
---
title: "Internationalization"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Internationalization}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
eval = FALSE
)
```
```{r setup}
library(datamods)
```
When using {datamods} modules, a simple way to modify labels display is provided for using a different language or simply use other labels.
There are 4 different ways to use new labels:
```r
# Using a supported language
set_i18n("fr")
# Using a named list
set_i18n(list("Some label" = "Its translation", ...))
# Using a data.framewith 2 columns
set_i18n(data.frame(label = c(...), translation = c(...)))
# Using a CSV file
set_i18n("path/to/file.csv")
```
## Integrated languages
The following languages are integrated in {datamods} :
* {height=16, style="height:16px"} english, the default.
* {height=16, style="height:16px"} french, activate with:
```{r}
set_i18n("fr")
```
* {height=16, style="height:16px"} macedonian, activate with:
```{r}
set_i18n("mk")
```
* {height=16, style="height:16px"} {height=16, style="height:16px"} brazilian portuguese, activate with:
```{r}
set_i18n("pt")
```
* {height=16, style="height:16px"} albanian, activate with:
```{r}
set_i18n("al")
```
* {height=16, style="height:16px"} chinese, activate with:
```{r}
set_i18n("cn")
```
* {height=16, style="height:16px"} spanish, activate with:
```{r}
set_i18n("es")
```
* {height=16, style="height:16px"} german, activate with:
```{r}
set_i18n("de")
```
* {height=16, style="height:16px"} turkish, activate with:
```{r}
set_i18n("tr")
```
* {height=16, style="height:16px"} korean, activate with:
```{r}
set_i18n("kr")
```
* {height=16, style="height:16px"} polish, activate with:
```{r}
set_i18n("pl")
```
* {height=16, style="height:16px"} japanese, activate with:
```{r}
set_i18n("ja")
```
If you want another language to be supported, you can submit a Pull Request to add a CSV file like the one used for french (file is located in `inst/i18n` folder in the package, you can see it [here on GitHub](https://github.com/dreamRs/datamods/blob/master/inst/i18n/fr.csv)).
## Using a list
You can change labels with a named `list`, where names correspond to the labels and values to the translation to use:
```r
options("datamods.i18n" = list(
"Import a dataset from an environment" = "Importer un jeu de données depuis l'environnement global",
"Select a data.frame:" = "Sélectionner un data.frame :",
...
))
```
## Using a data.frame
You can change labels with a `data.frame` with two columns `label` (the original label) and `translation` (the new label to display):
```r
set_i18n(data.frame(
label = c("Import a dataset from an environment", "Select a data.frame:", ...),
translation = c("Importer un jeu de données depuis l'environnement global", "Sélectionner un data.frame :", ...)
))
```
## Using a file
Use a CSV file with same structure than `data.frame` above:
```r
set_i18n("path/to/file.csv")
```
An example of file is shown below.
## All labels
Here's the file used for french translation with all labels used in the package:
```{r, echo=FALSE, eval=TRUE, comment=""}
cat(readLines(system.file("i18n", "fr.csv", package = "datamods"), encoding = "UTF-8"), sep = '\n')
```