-
Notifications
You must be signed in to change notification settings - Fork 57
/
Copy pathcount.R
95 lines (80 loc) · 2.21 KB
/
count.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#' Count observations by group
#'
#' This is a method for the dplyr [count()] generic. It is translated using
#' `.N` in the `j` argument, and supplying groups to `keyby` as appropriate.
#'
#' @param .data A [lazy_dt()]
#' @inheritParams dplyr::count
#' @importFrom dplyr count
#' @export
#' @examples
#' library(dplyr, warn.conflicts = FALSE)
#'
#' dt <- lazy_dt(dplyr::starwars)
#' dt %>% count(species)
#' dt %>% count(species, sort = TRUE)
#' dt %>% count(species, wt = mass, sort = TRUE)
count.dtplyr_step <- function(.data, ..., wt = NULL, sort = FALSE, name = NULL) {
if (!missing(...)) {
out <- group_by(.data, ..., .add = TRUE)
.groups <- "drop"
} else {
out <- .data
.groups <- "keep"
}
out <- tally_count(out, {{ wt }}, sort, name, .groups)
out
}
#' @importFrom dplyr add_count
#' @export
add_count.dtplyr_step <- function(.data, ..., wt = NULL, sort = FALSE, name = NULL) {
if (!missing(...)) {
out <- group_by(.data, ..., .add = TRUE)
} else {
out <- .data
}
out <- dplyr::add_tally(out, wt = !!enquo(wt), sort = sort, name = name)
out <- group_by(out, !!!syms(group_vars(.data)))
out
}
#' @importFrom dplyr tally
#' @export
tally.dtplyr_step <- function(.data, wt = NULL, sort = FALSE, name = NULL) {
tally_count(.data, {{ wt }}, sort, name, "drop_last")
}
# Helpers -----------------------------------------------------------------
tally_count <- function(.data, wt = NULL, sort = FALSE, name = NULL, .groups = "drop_last") {
wt <- enquo(wt)
if (quo_is_null(wt)) {
n <- expr(n())
} else {
n <- expr(sum(!!wt, na.rm = TRUE))
}
name <- check_name(name, .data$groups)
out <- summarise(.data, !!name := !!n, .groups = .groups)
if (sort) {
out <- arrange(out, desc(!!sym(name)))
}
out
}
check_name <- function(name, vars) {
if (is.null(name)) {
name <- n_name(vars)
if (name != "n") {
inform(c(
glue::glue("Storing counts in `{name}`, as `n` already present in input"),
i = "Use `name = \"new_name\"` to pick a new name."
))
}
} else if (!is_string(name)) {
abort("`name` must be a string")
}
name
}
n_name <- function(x) {
name <- "n"
while (name %in% x) {
name <- paste0("n", name)
}
name
}