【发布时间】:2021-01-21 16:33:07
【问题描述】:
我发布这个是希望有人可以解释这里的行为。也许这可以为其他人节省一些时间来跟踪如何修复类似的错误。
答案可能在this vignette by Hadley Wickham and Lionel Henry 的某个地方。然而,像我这样的人需要数周的学习才能将这些点联系起来。
我正在从远程数据库运行多个查询,然后将它们组合到一个 data.table 中。我将“part_”前缀添加到每个查询结果的名称中,并将ls() 和mget() 与data.table 的rbindlist() 结合使用。
这行得通:
results_all <- rbindlist(mget(ls(pattern = "part_", )))
我可能从list data.tables in memory and combine by row (rbind) 学到了这种方法,知道如何做是很有帮助的。
为了可读性,我通常更喜欢使用 magrittr 管道(或与 data.table 链接),尤其是像这样的项目,因为我使用 dplyr 来查询数据库。然而这段代码会导致错误:
results_all <- ls(pattern = "part_", ) %>%
mget() %>%
rbindlist()
错误为Error: value for ‘part_a’ not found,其中part_a 是ls() 返回的字符向量中的第一个对象名称。
搜索该错误消息,我遇到了in this data.table Github issue 的讨论。通过阅读,我尝试在 mget() 中设置“inherits = TRUE”,如下所示:
results_all <- ls(pattern = "part_", ) %>%
mget(inherits = TRUE) %>%
rbindlist()
这行得通。因此,将ls() 的结果传送到mget() 时会发生错误。鉴于在 mget() 中嵌套 ls() 是可行的,我的猜测是它与管道和“环境的封闭框架”有关。
在写这篇文章时,我遇到了Unexpected error message while joining data.table with rbindlist() using mget()。从那里的讨论中我发现这也有效。
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))
【问题讨论】:
-
请创建一个可重现的示例,包括所有输入和
library语句。有关发布说明,请参阅r 标签页顶部的信息。 -
好的,我加了一个。看起来@bcarlsen 已经解释了正在发生的事情。我认为在将 ls() 返回的任何对象名称传递给 mget() 时,您会看到相同的行为。
-
在您链接的论文中,您感兴趣的是有关词汇副作用的部分。阅读 Hadley 的 Advanced R 中有关环境的部分也会有所帮助。
-
谢谢@Moody_Mudskipper。 Advanced R 的解释很好,并且使用简单的语言。感谢您指点我那里(我也从您的 Twitter 帖子中学到了很多东西)。这些年来,我从 SO 那里学到了很多技巧。考虑到我在 bcarlsen 的回答下的评论中引用的“建立理解”SO 博客文章,我想知道为什么我的问题到目前为止被两次否决。也许这个问题对许多人来说是显而易见的。想到人们从电子表格过渡到 R,我会非常怀疑。
-
我很高兴能帮助科里。我认为你不应该投反对票,而且这个问题一点也不明显,所以不要难过。我相信你被否决了,因为你的例子不是最小的,关于数据库、rbindlist、数据框的所有部分都与问题无关。我知道您想设置上下文,但
x <- 1; y <-2; ls() %>% mget()在这里就足够了。
标签: r data.table magrittr mget