如何在SE案例中使用nesting_

时间:2016-10-21 16:00:52

标签: r tidyr nse

我正在努力学习如何使用hadleyverse进行编程。我已经阅读了NSE和lazyeval的小插曲,但我还是输了......

我试图将tidyr :: complete帮助页面上给出的示例翻译成SE案例。

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))

我的最终目标是能够使用指定为:

的变量执行相同的操作
v1 <- 'group'
v2 <- 'item_id, item_name'

但在我尝试之前,我需要能够直接使用列名来解决问题。 要开始,即使我知道它不是我想要的,这至少不会引发错误:

df %>% complete_(list(~group, ~item_id, ~item_name))

我无法弄清楚如何包含嵌套_&#39;
我尝试过的事情:

df %>% complete_(~group, nesting_(~item_id, ~item_name)) 
# Error in nesting_(~item_id, ~item_name) : unused argument (~item_name)

df %>% complete_(~group, nesting_(list(~item_id, ~item_name)))
# Error: Each variable must be named. 
# Problem variables: 1, 2 

df %>% complete_(~group, nesting_(alist(~item_id, ~item_name)))
# Error: Each variable must be named. 
# Problem variables: 1, 2 

df %>% complete_(~group, nesting_(list('item_id' = item_id, 'item_name' = item_name)))
# Error in stopifnot(is.list(x)) : object 'item_id' not found

df %>% complete_(~group, nesting_(list('item_id' = df$item_id, 'item_name' = df$item_name)))
# No syntax error, but doesn't expand...

df %>% complete_(~group, nesting_(named_dots(item_id, item_name)))
# Error: Each variable must be a 1d atomic vector or list.
# Problem variables: 'item_id', 'item_name'

df %>% complete_(~group, nesting_(list('item_id' = item_id, 'item_name' = item_name)))
# Error in stopifnot(is.list(x)) : object 'item_id' not found

df %>% complete_(~group, nesting_(list(as.name(item_id), as.name(item_name))))
# Error in as.name(item_id) : object 'item_id' not found

df %>% complete_(~group, nesting_(as.name(item_id), as.name(item_name)))
# Error in nesting_(as.name(item_id), as.name(item_name)) : 
#   unused argument (as.name(item_name))

感谢您的帮助!!

3 个答案:

答案 0 :(得分:2)

感谢@aosmith的建议,我破解了这种解决方法 这可能不是最好/最正确的方式,但似乎有效。

从最后一个有效的陈述开始:

v1 <- 'group'
v2 <- c("item_id", "item_name")
df %>% complete_(list(as.name(v1), ~nesting_(setNames(list(item_id, item_name), v2))))

我玩了setNames调用,看看它做了什么:

setNames(list(df$item_id, df$item_name), v2)
$item_id
[1] 1 2 2

$item_name
[1] "a" "b" "b"

并意识到它只是对v2中命名的df列进行了子集化。所以我试着通过select_:

做同样的事情
df %>% complete_(list(as.name(v1), ~nesting_(select_(., .dots = v2))))
# A tibble: 4 × 5
  group item_id item_name value1 value2
  <dbl>   <dbl>     <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

答案 1 :(得分:1)

我让complete_nesting_像这样一起工作:

df %>% complete_(list(~group, ~nesting_(list(item_id = item_id, item_name = item_name))))

查看nesting_的代码,看起来命名列表来自tibble::as_data_frame的使用。

但是,当您实际开始使用命名变量时,上面的代码没有多大帮助。事情仍适用complete_确定:

df %>% complete_(list(as.name(v1), ~nesting_(list(item_id = item_id, item_name = item_name))))

您可以通过nesting_制作setNames的命名列表以及名称的矢量:

v2 <- c("item_id", "item_name")
df %>% complete_(list(as.name(v1), ~nesting_(setNames(list(item_id, item_name), v2))))

但我找不到使用nesting_名称列表的解决方案。我的失败涉及像

这样的事情
df %>% complete_(list(as.name(v1), ~nesting_(setNames(lapply(v2, as.name), v2))))
  

错误:每个变量必须是1d原子向量或列表。问题   变量:'item_id','item_name'

我没有尝试过那么多,但它可能会给你一个起点。

答案 2 :(得分:0)

另一种可能性是:

v1 <- 'group'
v2 <- c('item_id', 'item_name')
df %>% complete_(c(v1, ~do.call(nesting, lapply(v2, as.name))))

  group item_id item_name value1 value2
  <dbl>   <dbl>     <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

这并没有使用&#34; SE&#34; nesting_(),而是利用了完成的参数可以被懒惰地评估的事实。我不相信这比ap53's answer above更可取,但它确实删除了select()的明确使用。