【问题标题】:Function evaluation in dplyr summarizedplyr 中的函数评估汇总
【发布时间】:2017-06-08 21:57:28
【问题描述】:

我认为我缺少关于 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 包装在自定义函数中(没有变化),并添加了一个打印语句来尝试调试它,但它尽可能接近,即使 x 的值为 1(类仍然是数字),contains(list(1), x) 在过滤器之外返回 TRUE,但在其中返回 FALSE

  1. 为什么?

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

  1. unique 和单参数函数如何同时作用于列?

【问题讨论】:

  • 不确定 purrr::contains 的性质,但 purrr::contains(list(1), dt0$x[1]) 返回 FALSE。尽管dt0$x[1]==1

标签: r function aggregate tidyverse


【解决方案1】:

似乎问题归结为比较的类别。在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)) 的调用仍将返回零行,因为第二个参数没有在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

【讨论】:

  • 嗯,好的。我认为真正让我失望的是(据我所知)很多函数,比如f,当给定一个数组时,将有效地为每个值i 返回一个f(i) 的数组大批。这让我觉得f 实际上被调用了很多次(因此应该使用包含),而实际上(据我所知)所有作用于过滤器中列的函​​数只是将数组传递给它们。
  • 如果您引用的 f(i) 行为发生,则逐个函数进行。 R 中的很多函数都是矢量化的,所以它们中的很多确实以这种方式运行,但其他函数(如 identical())没有矢量化,因此如果需要,由用户进行迭代。在某些情况下,您也可以使用Vectorize()(例如:v_identical = Vectorize(identical, 'y'); v_identical(1,c(1,1))
猜你喜欢
  • 2018-10-06
  • 1970-01-01
  • 2017-03-19
  • 1970-01-01
  • 2019-03-23
  • 2021-10-14
  • 1970-01-01
  • 2018-05-31
  • 2021-01-25
相关资源
最近更新 更多