diff --git a/DESCRIPTION b/DESCRIPTION index 35d2ebcfa0..1c8de59242 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -22,7 +22,7 @@ BugReports: https://github.com/tidyverse/dplyr/issues Depends: R (>= 3.5.0) Imports: - cli (>= 3.4.0), + cli (>= 3.6.2), generics, glue (>= 1.3.2), lifecycle (>= 1.0.3), @@ -30,7 +30,7 @@ Imports: methods, pillar (>= 1.9.0), R6, - rlang (>= 1.1.0), + rlang (>= 1.1.3), tibble (>= 3.2.0), tidyselect (>= 1.2.0), utils, diff --git a/R/generics.R b/R/generics.R index a9155f1a44..cfb440e838 100644 --- a/R/generics.R +++ b/R/generics.R @@ -63,7 +63,9 @@ #' #' * `summarise()` and `reframe()` work similarly to `mutate()` but the data #' modified by `dplyr_col_modify()` comes from `group_data()` or is built -#' from `.by`. +#' from `.by`. Note that this means that the data frames returned by +#' `summarise()` and `reframe()` are fundamentally new data frames, and +#' will not retain any custom subclasses or attributes. #' #' * `select()` uses 1d `[` to select columns, then `names<-` to rename them. #' `rename()` just uses `names<-`. `relocate()` just uses 1d `[`. diff --git a/man/dplyr_extending.Rd b/man/dplyr_extending.Rd index 72d5106e6d..0aec418efe 100644 --- a/man/dplyr_extending.Rd +++ b/man/dplyr_extending.Rd @@ -82,7 +82,9 @@ It also uses 1d \code{[} to implement \code{.keep}, and will call \code{relocate either \code{.before} or \code{.after} are supplied. \item \code{summarise()} and \code{reframe()} work similarly to \code{mutate()} but the data modified by \code{dplyr_col_modify()} comes from \code{group_data()} or is built -from \code{.by}. +from \code{.by}. Note that this means that the data frames returned by +\code{summarise()} and \code{reframe()} are fundamentally new data frames, and +will not retain any custom subclasses or attributes. \item \code{select()} uses 1d \code{[} to select columns, then \verb{names<-} to rename them. \code{rename()} just uses \verb{names<-}. \code{relocate()} just uses 1d \code{[}. \item \code{inner_join()}, \code{left_join()}, \code{right_join()}, and \code{full_join()} diff --git a/tests/testthat/_snaps/context.md b/tests/testthat/_snaps/context.md index a0b60d1fd4..08b03fb5be 100644 --- a/tests/testthat/_snaps/context.md +++ b/tests/testthat/_snaps/context.md @@ -40,5 +40,5 @@ Code group_labels_details(c(a = 1, b = 2)) Output - [1] "`a = 1`, `b = 2`" + [1] "`a = 1` and `b = 2`" diff --git a/tests/testthat/_snaps/summarise.md b/tests/testthat/_snaps/summarise.md index 318edcb751..3f80a60a5a 100644 --- a/tests/testthat/_snaps/summarise.md +++ b/tests/testthat/_snaps/summarise.md @@ -124,7 +124,7 @@ Error in `summarise()`: i In argument: `a = rlang::env(a = 1)`. - i In group 1: `x = 1`, `y = 1`. + i In group 1: `x = 1` and `y = 1`. Caused by error: ! `a` must be a vector, not an environment. Code diff --git a/tests/testthat/test-summarise.R b/tests/testthat/test-summarise.R index eec046542a..2a0db3b23f 100644 --- a/tests/testthat/test-summarise.R +++ b/tests/testthat/test-summarise.R @@ -60,21 +60,44 @@ test_that("no expressions yields grouping data", { expect_equal(summarise(gf, !!!list()), tibble(x = 1:2)) }) -test_that("preserved class, but not attributes", { +test_that("doesn't preserve attributes", { df <- structure( data.frame(x = 1:10, g1 = rep(1:2, each = 5), g2 = rep(1:5, 2)), meta = "this is important" ) out <- df %>% summarise(n = n()) - expect_s3_class(out, "data.frame", exact = TRUE) expect_null(attr(out, "res")) out <- df %>% group_by(g1) %>% summarise(n = n()) - # expect_s3_class(out, "data.frame", exact = TRUE) expect_null(attr(out, "res")) }) +test_that("strips off subclass", { + # We consider the data frame returned by `summarise()` to be + # "fundamentally a new data frame" + + df <- new_data_frame(list(a = 1), class = "myclass") + out <- df %>% summarise(n = n()) + expect_s3_class(out, "data.frame", exact = TRUE) + out <- df %>% summarise(.by = a, n = n()) + expect_s3_class(out, "data.frame", exact = TRUE) + + df <- new_tibble(list(a = 1), class = "myclass") + out <- df %>% summarise(n = n()) + expect_s3_class(out, class(tibble()), exact = TRUE) + out <- df %>% summarise(.by = a, n = n()) + expect_s3_class(out, class(tibble()), exact = TRUE) + + gdf <- group_by(tibble(a = 1), a) + df <- gdf + class(df) <- c("myclass", class(gdf)) + out <- df %>% summarise(n = n(), .groups = "drop") + expect_s3_class(out, class(tibble()), exact = TRUE) + out <- df %>% summarise(n = n(), .groups = "keep") + expect_s3_class(out, class(gdf), exact = TRUE) +}) + test_that("works with unquoted values", { df <- tibble(g = c(1, 1, 2, 2, 2), x = 1:5) expect_equal(summarise(df, out = !!1), tibble(out = 1))