以下功能的目的是允许更容易地进行自引用分配。 (如此处所示:Referencing a dataframe recursively)
所以不是
# this
myDataFrame$variable[is.na(myDataFrame$variable)] <- 0
# we can have this:
NAto0(myDataFrame$variable)
这些函数适用于向量,但在* ply'ing
时效果较差我遇到了关于函数match.call()
的{{1}}部分的两个问题(代码如下)。问题是:
我已将参数selfAssign()
添加到n
,这最终适用于selfAssign(.)
语句。我想知道我是否可以某种方式使用eval
类似于
n
也许在selfAssign中有类似 sapply(df, NAto0, n=2)
的东西(我试过,要么我没有把它弄好,要么它不起作用)
任何建议都会非常感谢。
<小时/> <小时/>
这些函数是selfAssign的包装器,是sys.parent(n)
调用中使用的函数。
*apply
NAtoNULL <- function(obj, n=1) {
# replace NA's with NULL
selfAssign(match.call()[[2]], is.na(obj), NULL, n=n+1)
}
NAto0 <- function(obj, n=1) {
# replace NA's with 0
selfAssign(match.call()[[2]], is.na(obj), 0, n=n+1)
}
NAtoVal <- function(obj, val, n=1) {
selfAssign(match.call()[[2]], is.na(obj), val, n=n+1)
}
ZtoNA <- function(obj, n=1) {
# replace 0's with NA
# TODO: this may have to be modified if obj is matrix
ind <- obj == 0
selfAssign(match.call()[[2]], ind, NA, n=n+1)
}
是执行工作的函数,错误来自哪里
selfAssign
答案 0 :(得分:1)
注意,我并不赞同这种类型的东西,但是支持理解R如何工作的愿望,以便你可以根据需要做这些事情。
以下仅适用于sapply
,因此它只能部分回答您的问题,但它确实列出了您可以采取的策略。正如我在之前的评论中所指出的那样,很难做到这一点,但我可以在sapply
电话的具体情况下回答1和2
sys.calls
获取跟踪堆栈sys.frame
和sys.parents
获取适当的评估环境一种非强大的说明性实现,使用您想要的策略类型将列表中的所有向量转换为NA:
get_sapply_call <- function(x) get_sapply_call_core(x) # To emulate your in-between functions
get_sapply_call_core <- function(x) {
if((c.len <- length(s.calls <- sys.calls())) < 4L) return("NULL")
if(s.calls[[c.len - 2L]][[1L]] == quote(lapply) & # Target sapply calls only
s.calls[[c.len - 3L]][[1L]] == quote(sapply) &
s.calls[[c.len - 1L]][[1L]] == quote(FUN)) {
mc.FUN <- s.calls[[c.len - 1L]]
mc.sa <- match.call(definition=sapply, s.calls[[c.len - 3L]]) # only need to match sapply b/c other calls are not user calls and as such structure is known
call.txt <- paste0(
as.character(mc.sa[[2L]]), "[[", mc.FUN[[2L]][[3L]],
"]] <- rep(NA, length(", as.character(mc.sa[[2L]]), "[[", mc.FUN[[2L]][[3L]],
"]]))"
)
call <- parse(text=call.txt)
eval(call, envir=sys.frame(sys.parents()[c.len - 3L]))
return(call.txt)
}
return("NULL")
}
df <- data.frame(a=1:10, b=letters[1:10])
sapply(df, get_sapply_call)
# a b
# "df[[1]] <- rep(NA, length(df[[1]]))" "df[[2]] <- rep(NA, length(df[[2]]))"
df
# a b
# 1 NA NA
# 2 NA NA
# 3 NA NA
# 4 NA NA
# ...
对于不同的*apply
函数,您将需要不同的逻辑,如果以某种其他方式间接调用函数,则需要更多不同的逻辑。此外,这绝对是一个快速而又脏的实现,因此即使对于sapply
,您也可能需要添加内容以使其更加健壮。并且无法保证sapply
实施在将来不会改变以上所有内容。
编辑:请注意,您完全可以回避match.call