使用tidyr的complete()函数,其中列名由变量指定

7

我使用tidyr::complete()函数时,用列名变量会遇到问题。

内置示例可以正常工作:

df <- data_frame(
 group = c(1:2, 1),
 item_id = c(1:2, 2),
 item_name = c("a", "b", "b"),
 value1 = 1:3,
 value2 = 4:6
)

df %>% complete(group, nesting(item_id, item_name)) 

然而,当我试图将列名提供为字符串时,它会产生错误。

gr="group"
id="item_id"
name="item_name"
df %>% complete_(gr, nesting_(id, name),fill = list(NA))

根据源代码,“nesting_”仅接受一个参数(列表)。 - Rich Scriven
它是否应该抛出一个错误呢?我在想。 - David Arenburg
@David Arenburg:当fill = list(NA)缺失时,它就会出现问题。 - ChriiSchee
2
哎呀,我知道 tidyr 可以做一些东西,但向你扔箭头是一个有趣的功能。 - David Arenburg
我已经做到了这一步,但是还没有让 complete_ 正常工作:df %>% complete(group, nesting_(setNames(list(.[[id]], .[[name]]), c(id, name)))) 另外,它很丑。 - alistaire
3个回答

6

更简单一些,现在可以使用tidyr 1.0.2中的代码df %>% complete(!!!syms(gr), nesting(!!!syms(id), !!!syms(name)))来完成它。


这应该是被接受的答案。顺便说一下,在这种情况下,只需要两个感叹号,例如 !!sym(gr) 而不是 !!!syms(gr),如此解释在这里 https://dev59.com/OlIH5IYBdhLWcg3wHJKn。 - Earlien
它不能处理未加引号的名称。 - Julien
对于未引用的情况,使用 !!sym(rlang::enexpr(col)) - Julien

2

现在 tidyr 已经采用了整洁评估,下划线变量(即complete_)已被弃用,因为它们的行为可以通过标准变量(complete)处理。

然而,completecrossingnesting 使用数据屏蔽技术,因此将变量转换为名称的方法是通过 .data[[var]] 代词(参见文档),因此您的情况变成了:

suppressPackageStartupMessages(
  library(tidyr)
)

df <- data.frame(
  group = c(1:2, 1),
  item_id = c(1:2, 2),
  item_name = c("a", "b", "b"),
  value1 = 1:3,
  value2 = 4:6
)

gr <- "group"
id <- "item_id"
name <- "item_name"

df %>% complete(
  .data[[gr]],
  nesting(.data[[id]],
          .data[[name]])
)
#> # A tibble: 4 x 5
#>   group item_id item_name value1 value2
#>   <dbl>   <dbl> <fct>      <int>  <int>
#> 1     1       1 a              1      4
#> 2     1       2 b              3      6
#> 3     2       1 a             NA     NA
#> 4     2       2 b              2      5

此内容由 reprex包 (v0.3.0) 于2020年02月28日创建

虽然不太优雅,但它能完成工作。


使用 tidyr v1.2.0 版本,结果为:Error in .data[["item_id"]]: ! 在 .data 中找不到列 item_id - tic-toc-choc

2

我认为complete_不能像complete那样与数据框或列表列一起使用是一个bug,但这里有一个解决方法,使用unite_separate来模拟nesting

df %>% unite_('id_name', c(id, name)) %>% 
    complete_(c(gr, 'id_name')) %>% 
    separate(id_name, c(id, name))

## # A tibble: 4 × 5
##   group item_id item_name value1 value2
## * <dbl>   <chr>     <chr>  <int>  <int>
## 1     1       1         a      1      4
## 2     1       2         b      3      6
## 3     2       1         a     NA     NA
## 4     2       2         b      2      5

感谢您的回答@alistaire,这对于小数据框来说很好用。但是当我在大对象上尝试该模式时,我会收到一个警告消息:在691968个位置处有太多的值:...并且该函数无法完成整个数据框。 - ChriiSchee
通常出现这种错误是因为数据中已经存在其他分隔符,导致分割次数过多。separate函数的sep参数默认为任何非字母数字字符,但您可以通过添加sep = '_'来将其限制为unite函数使用的分隔符(默认为_)。 - alistaire
你是对的。那确实是我数据集中的情况。谢谢。 - ChriiSchee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接