R 管道、mget 和环境
R pipe, mget, and environments
我发布这个是希望有人能解释这里的行为。也许这可以为其他人节省一些时间来查找如何修复类似的错误。
答案可能就在 this vignette by Hadley Wickham and Lionel Henry 的某个地方。然而,像我这样的人需要数周的学习才能将这些点联系起来。
我 运行 来自远程数据库的大量查询,然后将它们组合成一个 data.table。我将“part_”前缀添加到每个查询结果的名称,并使用 ls()
和 mget()
与 data.table 的 rbindlist()
组合它们。
这个有效:
results_all <- rbindlist(mget(ls(pattern = "part_", )))
我可能从 那里学到了这种方法,知道如何确定是很有帮助的。
为了可读性,我通常更喜欢使用 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() 有效,我的猜测是它与管道和“环境的封闭框架”有关。
在写这篇文章时,我遇到了 。从那里的讨论中我发现这也有效。
results_all <- ls(pattern = "part_", ) %>%
mget(envir = .GlobalEnv) %>%
rbindlist()
再次,我希望有人可以为那些希望了解更多关于环境在 R 中如何工作的人们解释发生了什么。
编辑:添加可重现的示例
根据对可重现答案的请求,运行 上面使用这三个 data.table 的代码(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))
管道运算符的 rhs
参数(在您的示例中,表达式 mget()
)永远不会被解释器评估为函数调用。管道运算符是一个中缀函数,它对其第二个参数 (rhs
) 执行 non-standard 评估。管道函数使用 RHS 表达式作为一种“模板”组合并执行新的函数调用。
本次新函数调用的调用环境是%>%
的函数环境,不是lhs
函数的调用环境,也不是全局环境。 .GlobalEnv
和 lhs
函数的调用环境在您的示例中恰好是相同的环境,并且该环境是 %>%
函数环境的父级,这就是为什么 inherits = TRUE
或将环境设置为 .GlobalEnv
适合您。
我发布这个是希望有人能解释这里的行为。也许这可以为其他人节省一些时间来查找如何修复类似的错误。
答案可能就在 this vignette by Hadley Wickham and Lionel Henry 的某个地方。然而,像我这样的人需要数周的学习才能将这些点联系起来。
我 运行 来自远程数据库的大量查询,然后将它们组合成一个 data.table。我将“part_”前缀添加到每个查询结果的名称,并使用 ls()
和 mget()
与 data.table 的 rbindlist()
组合它们。
这个有效:
results_all <- rbindlist(mget(ls(pattern = "part_", )))
我可能从
为了可读性,我通常更喜欢使用 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() 有效,我的猜测是它与管道和“环境的封闭框架”有关。
在写这篇文章时,我遇到了
results_all <- ls(pattern = "part_", ) %>%
mget(envir = .GlobalEnv) %>%
rbindlist()
再次,我希望有人可以为那些希望了解更多关于环境在 R 中如何工作的人们解释发生了什么。
编辑:添加可重现的示例
根据对可重现答案的请求,运行 上面使用这三个 data.table 的代码(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))
管道运算符的 rhs
参数(在您的示例中,表达式 mget()
)永远不会被解释器评估为函数调用。管道运算符是一个中缀函数,它对其第二个参数 (rhs
) 执行 non-standard 评估。管道函数使用 RHS 表达式作为一种“模板”组合并执行新的函数调用。
本次新函数调用的调用环境是%>%
的函数环境,不是lhs
函数的调用环境,也不是全局环境。 .GlobalEnv
和 lhs
函数的调用环境在您的示例中恰好是相同的环境,并且该环境是 %>%
函数环境的父级,这就是为什么 inherits = TRUE
或将环境设置为 .GlobalEnv
适合您。