diff --git a/r/NAMESPACE b/r/NAMESPACE index 567353876ca..4cc8df46d33 100644 --- a/r/NAMESPACE +++ b/r/NAMESPACE @@ -22,7 +22,9 @@ S3method("names<-",ArrowTabular) S3method(Ops,ArrowDatum) S3method(Ops,Expression) S3method(Ops,array_expression) +S3method(all,ArrowDatum) S3method(all,equal.ArrowObject) +S3method(any,ArrowDatum) S3method(as.character,ArrowDatum) S3method(as.character,FileFormat) S3method(as.character,FragmentScanOptions) diff --git a/r/R/compute.R b/r/R/compute.R index 1b79d76f037..0641bf1615c 100644 --- a/r/R/compute.R +++ b/r/R/compute.R @@ -186,6 +186,35 @@ unique.ArrowDatum <- function(x, incomparables = FALSE, ...) { call_function("unique", x) } +#' @export +any.ArrowDatum <- function(..., na.rm = FALSE){ + + a <- collect_arrays_from_dots(list(...)) + result <- call_function("any", a) + + if (!na.rm && a$null_count > 0 && !as.vector(result)) { + # Three-valued logic: with na.rm = FALSE, any(c(TRUE, NA)) returns TRUE but any(c(FALSE, NA)) returns NA + # TODO: C++ library should take na.rm for any/all (like ARROW-9054) + Scalar$create(NA) + } else { + result + } +} + +#' @export +all.ArrowDatum <- function(..., na.rm = FALSE){ + + a <- collect_arrays_from_dots(list(...)) + result <- call_function("all", a) + + if (!na.rm && a$null_count > 0 && as.vector(result)) { + # See comment above in any() about three-valued logic + Scalar$create(NA) + } else { + result + } +} + #' `match` and `%in%` for Arrow objects #' #' `base::match()` is not a generic, so we can't just define Arrow methods for diff --git a/r/tests/testthat/test-compute-aggregate.R b/r/tests/testthat/test-compute-aggregate.R index 77010579d78..0621b7779c7 100644 --- a/r/tests/testthat/test-compute-aggregate.R +++ b/r/tests/testthat/test-compute-aggregate.R @@ -351,3 +351,33 @@ test_that("value_counts", { expect_identical(as.data.frame(value_counts(a)), result_df) expect_identical(as.vector(value_counts(a)$counts), result_df$counts) }) + +test_that("any.Array and any.ChunkedArray", { + + data <- c(1:10, NA, NA) + + expect_vector_equal(any(input > 5), data) + expect_vector_equal(any(input < 1), data) + expect_vector_equal(any(input < 1, na.rm = TRUE), data) + + data_logical <- c(TRUE, FALSE, TRUE, NA, FALSE) + + expect_vector_equal(any(input), data_logical) + expect_vector_equal(any(input, na.rm = TRUE), data_logical) + +}) + +test_that("all.Array and all.ChunkedArray", { + + data <- c(1:10, NA, NA) + + expect_vector_equal(all(input > 5), data) + expect_vector_equal(all(input < 11), data) + expect_vector_equal(all(input < 11, na.rm = TRUE), data) + + data_logical <- c(TRUE, TRUE, NA) + + expect_vector_equal(all(input), data_logical) + expect_vector_equal(all(input, na.rm = TRUE), data_logical) + +})