Hi everyone,
I am working on developing a R package that needs to coerce vectors, factors, data.frame, tibbles, data.tables, and list into a matrix of character values. For the coercion, I have created a function called char_matrix and returns a matrix of character values, where the column names of the matrix should be the original object or the columns of the original object. You can how I programmed this below. When I test the function using a vector of values only, a matrix is returned with the appropriate column name. However, when I put char_matrix within another function like main_fun, which is listed below, the returned character matrix has a column name of the parameter name and not the R object name.
Would someone be able to assist in adjusting char_matrix, so the appropriate R object name is returned as a column name when char_matrix is used within another function?
I have provided some examples below demonstrating the issue I am having. Thank you for the help!
Erik
# Create functions ####
## char_matrix ####
char_matrix <- function(x = x) {
# Helper: Null-coalescing operator
`%||%` <- function(a, b) {
if (!is.null(x = a)) a else b
}
# Capture variable name as string for fallback column name ####
var_name <- deparse(expr = substitute(expr = x))
var_name <- gsub(
x = var_name,
pattern = ".*\\$",
replacement = "",
perl = FALSE
)
# Handle factor or character vector ####
if (is.factor(x = x)) {
x <- as.character(x = x)
}
# Simple vector to single-column character matrix ####
if (is.atomic(x = x) && is.vector(x = x)) {
out <- matrix(data = as.character(x = x), ncol = 1)
colnames(x = out) <- var_name
return(out)
}
# List input: handle unequal-length elements with padding ####
if (
is.list(x = x) && !inherits(x = x, what = c("data.frame", "data.table"))
) {
# Creating padded character list ####
max_len <- max(sapply(X = x, FUN = length))
padded <- lapply(
X = x,
FUN = function(xx) {
col_char <- as.character(x = xx)
length(x = col_char) <- max_len # pads with NA automatically
return(col_char)
}
)
# Creating character matrix ####
out <- do.call(what = "cbind", args = padded)
colnames(x = out) <- names(x = x) %||% paste0("V", seq_along(padded))
return(out)
}
# data.frame, data.table, or tibble ####
if (inherits(x = x, what = c("data.frame", "data.table"))) {
out <- as.matrix(
x = data.frame(lapply(x, as.character), stringsAsFactors = FALSE)
)
colnames(x = out) <- colnames(x = x)
return(out)
}
# Matrix input ####
if (is.matrix(x = x)) {
out <- apply(X = x, MARGIN = c(1, 2), FUN = as.character)
colnames(x = out) <- colnames(x = x)
return(out)
}
# Throwing an error if coercion fails ####
stop(
paste0(
"x must be a vector, matrix, data.frame, data.table, tibble, factor,",
" or list."
)
)
}
## Main function ####
main_fun <- function(y) {
if (!inherits(x = y, what = "matrix")) {
tmp <- try(expr = y <- char_matrix(x = y), silent = TRUE)
if (inherits(x = tmp, what = "try-error")) {
stop(
paste0(
"y must be a vector, matrix, data.frame, data.table, tibble, factor,",
" or list."
)
)
}
}
return(y)
}
# Generate data ####
z <- sample(x = letters[1:3], size = 100, replace = TRUE)
# Show char_matrix working outside of main function ####
char_working <- char_matrix(x = z)
colnames(char_working)
# Show char_matrix not working within main function ####
char_not_working <- main_fun(y = z)
colnames(char_not_working)