Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closes #271 add_hms: add hms to xportr.numeric_types and add details to xpor… #277

Merged
merged 3 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# xportr (development version)

* `"hms"` was added to the default value of the `xportr.numeric_types` option.
This ensures that `{xportr}` works smoothly with variables created by
`admiral::derive_vars_dtm_to_tm()`. (#271)

* More details were added to the messages of `xportr_type()`. (#271)

# xportr 0.4.1

## New Feature
Expand Down
32 changes: 30 additions & 2 deletions R/messages.R
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a good opportunity for some snapshot testing with all these additional messages? We can make into separate issue to move this along

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would make sense. I've added no snapshot tests for the new messages because snapshot testing is not used in xportr so far.

Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,39 @@ type_log <- function(meta_ordered, type_mismatch_ind, verbose) {

if (length(type_mismatch_ind) > 0) {
cli_h2("Variable type mismatches found.")
cli_alert_success("{ length(type_mismatch_ind) } variables coerced")
cli_alert_success("{ length(type_mismatch_ind) } variable{?s} coerced")

meta_mismatch <- meta_ordered[type_mismatch_ind, ]
message <- glue(
"Variable type(s) in dataframe don't match metadata: ",
"{encode_vars(meta_ordered[type_mismatch_ind, 'variable'])}"
"{encode_vars(meta_ordered[type_mismatch_ind, 'variable'])}\n",
paste0(
"- `", meta_mismatch$variable, "` was coerced to ",
ifelse(meta_mismatch$type.y == "_character", "<character>", "<numeric>"),
". (type in data: ", meta_mismatch$orig_type_data, ", type in metadata: ",
meta_mismatch$orig_type_meta, ")",
collapse = "\n"
),
paste(
"\ni Types in metadata considered as character (xportr.character_metadata_types option):",
encode_vals(getOption("xportr.character_metadata_types")),
collapse = " "
),
paste(
"\ni Types in metadata considered as numeric (xportr.numeric_metadata_types option):",
encode_vals(getOption("xportr.numeric_metadata_types")),
collapse = " "
),
paste(
"\ni Types in data considered as character (xportr.character_types option):",
encode_vals(getOption("xportr.character_types")),
collapse = " "
),
paste(
"\ni Types in data considered as numeric (xportr.numeric_types option):",
encode_vals(getOption("xportr.numeric_types")),
collapse = " "
)
)

xportr_logger(message, verbose)
Expand Down
68 changes: 34 additions & 34 deletions R/options.R
Original file line number Diff line number Diff line change
Expand Up @@ -15,42 +15,42 @@
#' @section Options with `options()`:
#'
#' \describe{
#' \item{xportr.df_domain_name}{defaults to `"dataset"`}:
#' The name of the domain "name" column in dataset metadata.
#' \item{xportr.df_label}{defaults to `"label"`}:
#' The column noting the dataset label in dataset metadata.
#' \item{xportr.domain_name}{defaults to `"dataset"`}:
#' The name of the domain "name" column in variable metadata.
#' \item{xportr.variable_name}{defaults to `"variable"`}:
#' The name of the variable "name" in variable metadata.
#' \item{xportr.type_name}{defaults to `"type"`}:
#' The name of the variable type column in variable metadata.
#' \item{xportr.label}{defaults to `"label"`}:
#' The name of the variable label column in variable metadata.
#' \item{xportr.length}{defaults to `"length"`}:
#' The name of the variable length column in variable metadata.
#' \item{xportr.order_name}{defaults to `"order"`}:
#' The name of the variable order column in variable metadata.
#' \item{xportr.format_name}{defaults to `"format"`}:
#' The name of the variable format column in variable metadata.
#' \item{xportr.format_verbose}{defaults to `"none"`}:
#' The default argument for the 'verbose' argument for `xportr_format`.
#' \item{xportr.label_verbose}{defaults to `"none"`}:
#' The default argument for the 'verbose' argument for `xportr_label`.
#' \item{xportr.length_verbose}{defaults to `"none"`}:
#' The default argument for the 'verbose' argument for `xportr_length`.
#' \item{xportr.type_verbose}{defaults to `"label"`}:
#' The default argument for the 'verbose' argument for `xportr_type`.
#' \item{xportr.character_types}{defaults to `"character"`}:
#' The default character vector used to explicitly coerce R classes to character XPT types.
#' \item{xportr.df_domain_name}{defaults to `"dataset"`\cr
#' The name of the domain "name" column in dataset metadata.}
#' \item{xportr.df_label}{defaults to `"label"`\cr
#' The column noting the dataset label in dataset metadata.}
#' \item{xportr.domain_name}{defaults to `"dataset"`\cr
#' The name of the domain "name" column in variable metadata.}
#' \item{xportr.variable_name}{defaults to `"variable"`\cr
#' The name of the variable "name" in variable metadata.}
#' \item{xportr.type_name}{defaults to `"type"`\cr
#' The name of the variable type column in variable metadata.}
#' \item{xportr.label}{defaults to `"label"`\cr
#' The name of the variable label column in variable metadata.}
#' \item{xportr.length}{defaults to `"length"`\cr
#' The name of the variable length column in variable metadata.}
#' \item{xportr.order_name}{defaults to `"order"`\cr
#' The name of the variable order column in variable metadata.}
#' \item{xportr.format_name}{defaults to `"format"`\cr
#' The name of the variable format column in variable metadata.}
#' \item{xportr.format_verbose}{defaults to `"none"`\cr
#' The default argument for the 'verbose' argument for `xportr_format`.}
#' \item{xportr.label_verbose}{defaults to `"none"`\cr
#' The default argument for the 'verbose' argument for `xportr_label`.}
#' \item{xportr.length_verbose}{defaults to `"none"`\cr
#' The default argument for the 'verbose' argument for `xportr_length`.}
#' \item{xportr.type_verbose}{defaults to `"label"`\cr
#' The default argument for the 'verbose' argument for `xportr_type`.}
#' \item{xportr.character_types}{defaults to `"character"`\cr
#' The default character vector used to explicitly coerce R classes to character XPT types.}
#' \item{xportr.character_metadata_types}{defaults to `c("character", "char", "text", "date", "posixct", "posixt",
#' "datetime", "time", "partialdate", "partialtime", "partialdatetime",
#' "incompletedatetime", "durationdatetime", "intervaldatetime")`}:
#' The default character vector used to explicitly coerce R classes to character XPT types.
#' \item{xportr.numeric_metadata_types}{defaults to `c("integer", "numeric", "num", "float")`}:
#' The default character vector used to explicitly coerce R classes to numeric XPT types.
#' \item{xportr.numeric_types}{defaults to `c("integer", "float", "numeric", "posixct", "posixt", "time", "date")`}:
#' The default character vector used to explicitly coerce R classes to numeric XPT types.
#' "incompletedatetime", "durationdatetime", "intervaldatetime")`\cr
#' The default character vector used to explicitly coerce R classes to character XPT types.}
#' \item{xportr.numeric_metadata_types}{defaults to `c("integer", "numeric", "num", "float")`\cr
#' The default character vector used to explicitly coerce R classes to numeric XPT types.}
#' \item{xportr.numeric_types}{defaults to ``r deparse(getOption("xportr.numeric_types"), width.cutoff = 500)``\cr
#' The default character vector used to explicitly coerce R classes to numeric XPT types.}
#' }
#'
#' @section Options with `xportr_options()`:
Expand Down
2 changes: 1 addition & 1 deletion R/split.R
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
#' adlb <- xportr_split(adlb, "LBCAT")
xportr_split <- function(.df, split_by = NULL) {
lifecycle::deprecate_warn(
when = "0.5.0",
when = "0.4.1",
what = "xportr_split()",
with = "xportr_write()",
details = "Please use the argument `max_gb_size` in the
Expand Down
17 changes: 10 additions & 7 deletions R/type.R
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#' Coerce variable type
#'
#' XPT v5 datasets only have data types of character and numeric. `xportr_type`
#' XPT v5 datasets only have data types of character and numeric. `xportr_type()`
#' attempts to collapse R classes to those two XPT types. The
#' 'xportr.character_types' option is used to explicitly collapse the class of a
#' column to character using `as.character`. Similarly, 'xportr.numeric_types'
#' will collapse a column to a numeric type. If no type is passed for a
#' variable, it is assumed to be numeric and coerced with `as.numeric()`.
#' column to character using `as.character()`. Similarly, 'xportr.numeric_types'
#' will collapse a column to a numeric type. (See `xportr_options()` for default
#' values of these options.) If no type is passed for a variable, it is assumed
#' to be numeric and coerced with `as.numeric()`.
#'
#' Certain care should be taken when using timing variables. R serializes dates
#' based on a reference date of 01/01/1970 where XPT uses 01/01/1960. This can
Expand All @@ -17,7 +18,7 @@
#'
#' @section Messaging: `type_log()` is the primary messaging tool for
#' `xportr_type()`. The number of column types that mismatch the reported type
#' in the metadata, if any, is reported by by `xportr_type()`. If there are any
#' in the metadata, if any, is reported by `xportr_type()`. If there are any
#' type mismatches, and the 'verbose' argument is 'stop', 'warn', or
#' 'message', each mismatch will be detailed with the actual type in the data
#' and the type noted in the metadata.
Expand Down Expand Up @@ -132,6 +133,8 @@ xportr_type <- function(.df,
by = "variable"
) %>%
mutate(
orig_type_data = type.x,
orig_type_meta = type.y,
# _character is used here as a mask of character, in case someone doesn't
# want 'character' coerced to character
type.x = if_else(type.x %in% character_types, "_character", type.x),
Expand All @@ -154,11 +157,11 @@ xportr_type <- function(.df,

# Check if variable types match
is_correct <- vapply(meta_ordered[["type.x"]] == meta_ordered[["type.y"]], isTRUE, logical(1))
# Use the original variable iff metadata is missing that variable
# Use the original variable if metadata is missing that variable
correct_type <- ifelse(is.na(meta_ordered[["type.y"]]), meta_ordered[["type.x"]], meta_ordered[["type.y"]])

# Walk along the columns and coerce the variables. Modifying the columns
# Directly instead of something like map_dfc to preserve any attributes.
# directly instead of something like map_dfc to preserve any attributes.
iwalk(
correct_type,
function(x, i, is_correct) {
Expand Down
38 changes: 19 additions & 19 deletions R/xportr-package.R
Original file line number Diff line number Diff line change
Expand Up @@ -12,82 +12,82 @@
#' \itemize{
#' \item{
#' xportr.df_domain_name - The name of the domain "name" column in dataset
#' metadata. Default: "dataset"
#' metadata. Default: `"dataset"`
#' }
#' \item {
#' xportr.df_label - The column noting the dataset label in dataset metadata.
#' Default: "label"
#' Default: `"label"`
#' }
#' \item{
#' xportr.domain_name - The name of the domain "name" column in variable
#' metadata. Default: "dataset"
#' metadata. Default: `"dataset"`
#' }
#' \item{
#' xportr.variable_name - The name of the variable "name" in variable
#' metadata. Default: "variable"
#' metadata. Default: `"variable"`
#' }
#' \item{
#' xportr.type_name - The name of the variable type column in variable
#' metadata. Default: "type"
#' metadata. Default: `"type"`
#' }
#' \item{
#' xportr.label - The name of the variable label column in variable metadata.
#' Default: "label"
#' Default: `"label"`
#' }
#' \item{
#' xportr.length - The name of the variable length column in variable
#' metadata. Default: "length"
#' metadata. Default: `"length"`
#' }
#' \item{
#' xportr.order_name - The name of the variable order column in variable
#' metadata. Default: "order"
#' metadata. Default: `"order"`
#' }
#' \item{
#' xportr.format_name - The name of the variable format column in variable
#' metadata. Default: "format"
#' metadata. Default: `"format"`
#' }
#' \item{
#' xportr.format_verbose - The default argument for the 'verbose' argument for
#' `xportr_format`. Default: "none"
#' `xportr_format`. Default: `"none"`
#' }
#' \item{
#' xportr.label_verbose - The default argument for the 'verbose' argument for
#' `xportr_label`. Default: "none"
#' `xportr_label`. Default: `"none"`
#' }
#' \item{
#' xportr.length_verbose - The default argument for the 'verbose' argument for
#' `xportr_length`. Default: "none"
#' `xportr_length`. Default: `"none"`
#' }
#' \item{
#' xportr.type_verbose - The default argument for the 'verbose' argument for
#' `xportr_type`. Default: "none"
#' `xportr_type`. Default: `"none"`
#' }
#' \item{
#' xportr.character_types - The default character vector used to explicitly
#' coerce R classes to character XPT types. Default: "character"
#' coerce R classes to character XPT types. Default: `"character"`
#' }
#' \item{
#' xportr.character_metadata_types - The default character vector used to explicitly
#' coerce R classes to character XPT types. Default: c("character", "char",
#' coerce R classes to character XPT types. Default: `c("character", "char",
#' "text", "date", "posixct", "posixt", "datetime", "time", "partialdate",
#' "partialtime", "partialdatetime", "incompletedatetime", "durationdatetime",
#' "intervaldatetime")`
#' }
#' \item{
#' xportr.numeric_metadata_types - The default character vector used to explicitly
#' coerce R classes to numeric XPT types. Default: c("integer", "numeric", "num", "float")
#' coerce R classes to numeric XPT types. Default: `c("integer", "numeric", "num", "float")`
#' }
#' \item{
#' xportr.numeric_types - The default character vector used to explicitly
#' coerce R classes to numeric XPT types. Default: c("integer", "float",
#' "numeric", "posixct", "posixt", "time", "date")
#' coerce R classes to numeric XPT types. Default:
#' ``r deparse(getOption("xportr.numeric_types"), width.cutoff = 500)``
#' }
#' }
#'
#' @section Updating Options:
#' \itemize{
#' \item{For a single session, an option can be changed by
#' `option(<optionToChange> = <NewValue>)`}
#' `options(<optionToChange> = <NewValue>)`.}
#' \item{To change an option for a single projects across sessions in that
#' projects, place the options update in the `.Rprofile` in that project
#' directory.}
Expand Down
2 changes: 1 addition & 1 deletion R/zzz.R
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ xportr_options_list <- list(
),
xportr.numeric_types = getOption(
"xportr.numeric_types",
c("integer", "float", "numeric", "posixct", "posixt", "time", "date")
c("integer", "float", "numeric", "posixct", "posixt", "time", "date", "hms")
)
)

Expand Down
Loading
Loading