dplyr 中的函数评估总结

Function evaluation in dplyr summarize

我想我遗漏了一些关于 R 如何评估事物的基本知识。考虑以下因素:

library("tidyverse")
dt0 <- tibble(x=1:10, y=11:20)
filter(dt0, 1==x)                          # Returns the first row
purrr::contains(list(1), 1)                # TRUE
filter(dt0, purrr::contains(list(1), x))   # Returns NO rows

我尝试将 contains 包装在一个自定义函数中(没有变化),并添加了一个打印语句来尝试调试它,但据我所知,即使 [=12 的值=] 为 1(class 仍然是数字),contains(list(1), x) returns TRUE 在过滤器外部,但 FALSE 在过滤器内部。

  1. 为什么?

可能相关,我真的不明白如何将列传递给 unique 之类的函数,但也传递给其他函数(比如我的自定义函数)。 (我知道你可以做,但不知道它是如何实现的。)我的自定义函数表现得好像它被调用了多次,对每个 x 值调用一次。 unique,但是,必须有 所有 值,是吗?

  1. unique 和单参数函数如何在列上工作?

问题似乎归结为比较的 类。在 purrr::contains() 的源代码中,正在调用 indentical() 来比较 dt0$xlist[[i]]dt0$x 的内容是整数,而 1 不是。所以要解决这个问题,我们可以使用 1L.

> is.integer(1:10)
[1] TRUE
> is.integer(1)
[1] FALSE

> identical((1:10)[1], 1)
[1] FALSE
> identical((1:10)[1], 1L)
[1] TRUE

然而,对 filter(dt0, purrr::contains(list(1L), x)) 的调用仍将 return 零行,因为第二个参数未在 purrr::contains() 中迭代。所以它正在检查整个列 x 是否包含在 list(1) 中(当然是 FALSE)。如果您想以这种方式使用 purrr::contains,则必须手动遍历第二个参数。

我认为语法不是那么优雅,但如果您想留在 purrr 中,您可以使用:

> filter(dt0, purrr::map_lgl(x,~purrr::contains(list(1L), .x)))
# A tibble: 1 × 2
      x     y
  <int> <int>
1     1    11