diff --git a/NAMESPACE b/NAMESPACE index 86adee5e0..428284184 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -22,6 +22,8 @@ S3method(nest,grouped_df) S3method(nest,tbl_df) S3method(nest_legacy,data.frame) S3method(nest_legacy,tbl_df) +S3method(pack,data.frame) +S3method(pack,tbl_df) S3method(pivot_longer,data.frame) S3method(pivot_wider,data.frame) S3method(replace_na,data.frame) @@ -38,6 +40,8 @@ S3method(unite_,data.frame) S3method(unnest,data.frame) S3method(unnest,rowwise_df) S3method(unnest_legacy,data.frame) +S3method(unpack,data.frame) +S3method(unpack,tbl_df) export("%>%") export(all_of) export(any_of) diff --git a/R/pack.R b/R/pack.R index b770cd730..fcf649a5a 100644 --- a/R/pack.R +++ b/R/pack.R @@ -27,6 +27,7 @@ #' @param ... <[`tidy-select`][tidyr_tidy_select]> Columns to pack, specified #' using name-variable pairs of the form `new_col = c(col1, col2, col3)`. #' The right hand side can be any valid tidy select expression. +#' Must be empty for `unpack()`, reserved for future extensions. #' @export #' @examples #' # Packing ============================================================= @@ -58,6 +59,22 @@ #' df %>% unpack(c(y, z)) #' df %>% unpack(c(y, z), names_sep = "_") pack <- function(.data, ..., .names_sep = NULL) { + UseMethod("pack") +} + +#' @export +pack.data.frame <- function(.data, ..., .names_sep = NULL) { + # The data frame print handles packed data frames poorly, so we want to + # convert data frames (but not subclasses) to tibbles + if (identical(class(.data), "data.frame")) { + .data <- as_tibble(.data) + } + + pack.tbl_df(.data, ..., .names_sep = .names_sep) +} + +#' @export +pack.tbl_df <- function(.data, ..., .names_sep = NULL) { cols <- enquos(...) if (any(names2(cols) == "")) { abort("All elements of `...` must be named") @@ -96,7 +113,24 @@ pack <- function(.data, ..., .names_sep = NULL) { #' #' See [vctrs::vec_as_names()] for more details on these terms and the #' strategies used to enforce them. -unpack <- function(data, cols, names_sep = NULL, names_repair = "check_unique") { +unpack <- function(data, cols, ..., names_sep = NULL, names_repair = "check_unique") { + check_dots_empty() + UseMethod("unpack") +} + +#' @export +unpack.data.frame <- function(data, cols, ..., names_sep = NULL, names_repair = "check_unique") { + # The data frame print handles packed data frames poorly, so we want to + # convert data frames (but not subclasses) to tibbles + if (identical(class(.data), "data.frame")) { + .data <- as_tibble(.data) + } + + unpack.tbl_df(data, cols, ..., names_sep = names_sep, names_repair = names_repair) +} + +#' @export +unpack.tbl_df <- function(data, cols, ..., names_sep = NULL, names_repair = "check_unique") { check_required(cols) cols <- tidyselect::eval_select(enquo(cols), data) diff --git a/man/pack.Rd b/man/pack.Rd index 667e121aa..eb3402dcc 100644 --- a/man/pack.Rd +++ b/man/pack.Rd @@ -7,12 +7,13 @@ \usage{ pack(.data, ..., .names_sep = NULL) -unpack(data, cols, names_sep = NULL, names_repair = "check_unique") +unpack(data, cols, ..., names_sep = NULL, names_repair = "check_unique") } \arguments{ \item{...}{<\code{\link[=tidyr_tidy_select]{tidy-select}}> Columns to pack, specified using name-variable pairs of the form \code{new_col = c(col1, col2, col3)}. -The right hand side can be any valid tidy select expression.} +The right hand side can be any valid tidy select expression. +Must be empty for \code{unpack()}, reserved for future extensions.} \item{data, .data}{A data frame.}