我试图在函数中的管道内部使用该n_distinct函数dplyr,并发现它以一种我意想不到的方式对我选择的语法敏感。这是一个玩具示例。
# preliminaries
library(tidyverse)
set.seed(123)
X <- data.frame(a1 = rnorm(10), a2 = rnorm(10), b = rep(LETTERS[1:5], times = 2), stringsAsFactors = FALSE)
print(X)
a1 a2 b
1 -0.56047565 1.2240818 A
2 -0.23017749 0.3598138 B
3 1.55870831 0.4007715 C
4 0.07050839 0.1106827 D
5 0.12928774 -0.5558411 E
6 1.71506499 1.7869131 A
7 0.46091621 0.4978505 B
8 -1.26506123 -1.9666172 C
9 -0.68685285 0.7013559 D
10 -0.44566197 -0.4727914 E
Run Code Online (Sandbox Code Playgroud)
好吧,现在假设我想对该数据框中所选列的名称迭代一个函数(幽默一下)。在这里,我将使用所选列中的值来过滤初始数据集,计算剩余的唯一 id 的数量,并将结果作为单行 tibble 返回,然后将其绑定到新的 tibble 中。当我在函数内创建一个新的 tibble,然后将n_distinct其作为自己的步骤应用于该 tibble 中的选定列时,我从n_distinct、 5 和 4 中获得了预期结果。
bind_rows(map(str_subset(colnames(X), "a"), function(i) {
subdf <- filter(X, !!sym(i) > 0)
value <- n_distinct(subdf$b)
tibble(y = i, n_uniq = value)
}))
# A tibble: 2 x 2
y n_uniq
<chr> <int>
1 a1 5
2 a2 4
Run Code Online (Sandbox Code Playgroud)
但是,如果我放入n_distinct管道并使用.来引用过滤后的小标题,代码会执行,但会得到不同且不正确的结果。
bind_rows(map(str_subset(colnames(X), "a"), function(i) {
value <- filter(X, !!sym(i) > 0) %>% n_distinct(.$b)
tibble(y = i, n_uniq = value)
}))
# A tibble: 2 x 2
y n_uniq
<chr> <int>
1 a1 5
2 a2 7
Run Code Online (Sandbox Code Playgroud)
那是怎么回事?.我是否误解了管道内部的使用?有什么时髦的吗n_distinct?
n_distinct接受多个参数,在这里您实际上将 tibble 和b列作为参数传递,因为默认情况下会传递管道的左侧。以下是获得预期输出的一些其他方法:
filter(X, !!sym(i) > 0) %>%
{n_distinct(.$b)}
filter(X, !!sym(i) > 0) %>%
with(n_distinct(b))
library(magrittr)
filter(X, !!sym(i) > 0) %$%
n_distinct(b)
Run Code Online (Sandbox Code Playgroud)
另外,与你的问题没有直接关系,这种事情有一个方便的功能
map_dfr(str_subset(colnames(X), "a"), function(i) {
value <- filter(X, !!sym(i) > 0) %>% {n_distinct(.$b)}
tibble(y = i, n_uniq = value)
})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
862 次 |
| 最近记录: |