2

我发布这个是希望有人可以解释这里的行为。也许这可以为其他人节省一些时间来追踪如何修复类似的错误。

答案很可能在Hadley Wickham 和 Lionel Henry 的这个小插曲中的某个地方。然而,像我这样的人需要数周的学习才能将这些点联系起来。

我正在从远程数据库运行许多查询,然后将它们组合到一个 data.table 中。我将“part_”前缀添加到每个单独的查询结果的名称中,并使用ls()data.tablemget()rbindlist()组合它们。

这有效:

results_all <- rbindlist(mget(ls(pattern = "part_", )))

我学会了这种方法,可能是从内存中的列表 data.tables 并按行组合 (rbind),知道如何确定是一件很有帮助的事情。

为了可读性,我通常更喜欢使用 magrittr 管道(或与 data.table 链接),尤其是像这样的项目,因为我使用 dplyr 来查询数据库。然而,这段代码会导致错误:

results_all <- ls(pattern = "part_", ) %>% 
 mget() %>%
 rbindlist()

错误读取Error: value for ‘part_a’ not foundwhere part_a 是返回的字符向量中的第一个对象名称ls()

搜索该错误消息,我在这个 data.table Github issue 中遇到了讨论。通过阅读,我尝试在 mget() 中设置“inherits = TRUE”,如下所示:

results_all <- ls(pattern = "part_", ) %>% 
 mget(inherits = TRUE) %>%
 rbindlist()

那行得通。ls()因此,在传递 to的结果时会发生错误mget()。鉴于在 mget() 中嵌套 ls() 有效,我的猜测是它与管道和“环境的封闭框架”有关。

在写这篇文章时,我在使用 mget() 将 data.table 与 rbindlist() 连接时遇到了 Unexpected 错误消息。从那里的讨论中我发现这也有效。

results_all <- ls(pattern = "part_", ) %>% 
 mget(envir = .GlobalEnv) %>%
 rbindlist()

同样,我希望有人可以为希望了解更多关于 R 环境如何工作的人们解释正在发生的事情。

编辑:添加可重现的示例

根据对可重现答案的请求,使用这三个 data.tables 运行上面的代码(data.frames 或 tibbles 的行为相同)应该可以做到。

part_a <- data.table(col1 = 1:10, col2 = sample(letters, 10))

part_b <- data.table(col1 = 11:20, col2 = sample(letters, 10))
  
part_c <- data.table(col1 = 21:30, col2 = sample(letters, 10)) 
4

1 回答 1

1

管道运算符的rhs参数(在您的示例中,表达式mget())永远不会被解释器评估为函数调用。rhs管道运算符是一个中缀函数,它对其第二个参数 ( )执行非标准评估。管道函数使用 RHS 表达式作为一种“模板”组合并执行一个新的函数调用。

这个新函数调用的调用环境是 的函数环境%>%,而不是函数的调用环境lhs或全局环境。.GlobalEnv并且函数的调用环境lhs恰好与您的示例中的环境相同,并且该环境是函数环境的父级%>%,这就是为什么inherits = TRUE或将环境设置为.GlobalEnv适合您的原因。

于 2020-10-06T18:48:28.040 回答