gpt4 book ai didi

如果在使用 data.table dplyr 时在函数中定义,则找不到 R 对象

转载 作者:行者123 更新时间:2023-12-04 15:21:54 30 4
gpt4 key购买 nike

备注 所描述的行为已在 dplyr 的开发版本中得到修复。您可以使用 devtools::install_github("hadley/dplyr") 安装 dplyr

请看这个最小的例子;我正在使用 dplyr v0.3.0.2 和 data.table v1.9.4

library(dplyr)
library(data.table)
f <- function(x, y, bad) {
z <- data.table(x,y, key = "x")
z2 <- z %>% group_by(x) %>% summarise(sum.bad = sum(y == bad))
z2
}

f(rnorm(100), rnorm(100) < 0, bad = FALSE)

当我运行上述内容时,我得到
Error in `[.data.table`(dt, , list(sum.bad = sum(y == bad)), by = vars) : 
object 'bad' not found

然而,坏是明确定义和范围内的。

如果我只是在函数之外运行它,它就可以工作
  x <- rnorm(100)
y <- rnorm(100) <0
bad <- FALSE
z <- data.table(x,y, key = "x")

z2 <- z %>% group_by(x) %>% summarise(sum.bad = sum(y == bad))
z2

这里有什么问题?它是 data.table 还是 dplyr 的错误?

最佳答案

似乎这是 dplyr 的问题正在为 data.table 调用设置环境。问题出现在 dplyr:::summarise_.grouped_dt功能。目前看起来像

function (.data, ..., .dots) 
{
dots <- lazyeval::all_dots(.dots, ..., all_named = TRUE)
for (i in seq_along(dots)) {
if (identical(dots[[i]]$expr, quote(n()))) {
dots[[i]]$expr <- quote(.N)
}
}
list_call <- lazyeval::make_call(quote(list), dots)
call <- substitute(dt[, list_call, by = vars], list(list_call = list_call$expr))
env <- dt_env(.data, parent.frame())
out <- eval(call, env)
grouped_dt(out, drop_last(groups(.data)), copy = FALSE)
}
<environment: namespace:dplyr>

如果我们调试该函数并在调用它时查看跟踪,我们会看到
where 1: summarise_.grouped_dt(.data, .dots = lazyeval::lazy_dots(...))
where 2: summarise_(.data, .dots = lazyeval::lazy_dots(...))
where 3: summarise(., sum.bad = sum(y == bad))
where 4: function_list[[k]](value)
where 5: withVisible(function_list[[k]](value))
where 6: freduce(value, `_function_list`)
where 7: `_fseq`(`_lhs`)
where 8: eval(expr, envir, enclos)
where 9: eval(quote(`_fseq`(`_lhs`)), env, env)
where 10: withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
where 11 at #3: z %>% group_by(x) %>% summarise(sum.bad = sum(y == bad))
where 12: f(rnorm(100), rnorm(100) < 0, bad = FALSE)

所以重要的线是
env <- dt_env(.data, parent.frame())

一。在这里,它设置环境路径,指定在调用中查找所有变量的位置。在这里它只是使用 parent.frame 来查找函数的调用位置,但是因为您实际上跳过了几个圈子才能从 summarize 到达该函数。调用内线 f() ,这似乎不是正确的父框架。如果相反,您运行
env <- dt_env(.data, parent.frame(2))

在 Debug模式下,这似乎实际上得到了正确的父框架。所以我认为问题是从 summarize() 跳转至 summarize_()因为这
ff <- function(x, y, bad) { 
z <- data.table(x,y, key = "x")
z2 <- z %>% group_by(x) %>% summarise_(.dots=list(sum.bad = quote(sum(y == bad))))
z2
}

ff(rnorm(100), rnorm(100) < 0, bad = FALSE)

似乎工作。所以真正需要设置正确环境的是dplyr。棘手的部分是,如果您调用 summarize,它似乎会有所不同。或 summarize_直接地。也许 summarise()调用 summarise_ 时可能会改变环境通过 eval() 拥有相同的 parent.frame .但我可能会将其作为错误报告提交,并让 Hadley 决定如何修复它。就像是
summarise <- function(.data, ...) {
call <- match.call()
call <- as.call(c(as.list(call)[1:2], list(.dots=as.list(call)[-(1:2)])))
call[[1]] <- quote(summarise_)
eval(call, envir=parent.frame())
}

将是一种“传统”的方式来做到这一点。不确定lazyeval 包是否有更好的方法来做到这一点。

data.table_1.9.2 测试和 dplyr_0.3.0.2

关于如果在使用 data.table dplyr 时在函数中定义,则找不到 R 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27773881/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com