管道内有n_distinct的异常行为

问题描述 投票:1回答:2

我试图在函数中的管道内使用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

[好,现在我想在该数据框中的选定列的名称上迭代一个函数(让我感到惊讶)。在这里,我将使用所选列中的值来过滤初始数据集,计算剩余的唯一ID的数量,并将结果作为单行标题返回,然后绑定到新标题中。当我在函数内创建一个新的小标题,然后将n_distinct应用于该小标题中的选定列作为其自己的步骤时,我从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

如果将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

这是怎么回事?我是否误解了管道内使用.n_distinct有点时髦吗?

r dplyr
2个回答
1
投票

n_distinct接受多个参数,实际上,您在这里同时传递了小标题和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)

而且,与您的问题没有直接关系,这种事情有一个便捷功能

map_dfr(str_subset(colnames(X), "a"), function(i) {

  value <- filter(X, !!sym(i) > 0) %>% {n_distinct(.$b)}

  tibble(y = i, n_uniq = value)

})

0
投票

这是我认为您所看到的内容的最小示例。

iris %>%
  n_distinct(.$Species)
# 149

n_distinct(iris$Species)
# 3

第一个实际上与执行此操作相同。 .$Species实际上是多余的。

iris %>%
  n_distinct()
# 149

我认为无需使用奇怪的语法就可以使用它来传递它。

iris %>%
  distinct(Species) %>% 
  count()
# 3
© www.soinside.com 2019 - 2024. All rights reserved.