使用'with'指定给data.frame`
下面是一个以两种不同方式分配的示例,一种有效,另一种无效:使用'with'指定给data.frame`,r,R,下面是一个以两种不同方式分配的示例,一种有效,另一种无效: library(datasets) dat <- as.data.frame(ChickWeight) dat$test1 <- with(dat, Time + weight) with(dat, test2 <- Time + weight) > colnames(dat) [1] "weight" "Time" "Chick" "Diet" "test1" 请注意,with是一个相当简单的^H
library(datasets)
dat <- as.data.frame(ChickWeight)
dat$test1 <- with(dat, Time + weight)
with(dat, test2 <- Time + weight)
> colnames(dat)
[1] "weight" "Time" "Chick" "Diet" "test1"
请注意,with是一个相当简单的^H^H^H^H^H短函数:
function (data, expr, ...)
eval(substitute(expr), data, enclos = parent.frame())
首先,让我们使用的功能复制:
eval( substitute(Time+weight), envir=dat, enclos=parent.frame() )
现在使用不同的机柜进行测试:
testEnv <- new.env()
eval( substitute(test3 <- Time+weight), envir=dat, enclos=testEnv )
ls( envir=testEnv )
testEnv用
将更改为
内的<代码>与
仅用于使变量可用,而不是更改变量
编辑:为了详细说明,我相信
with
和in
都会创建一个新的环境,并用给定的类似列表的对象(如数据框)填充它,然后在该环境中计算给定的表达式。不同之处在于with
返回表达式的结果并丢弃环境,而中的返回环境(转换回最初的类,例如data.frame)。无论哪种方式,在表达式中进行的任何赋值都可能在创建的环境中执行,而with
将放弃该环境。这就解释了为什么在使用(dat,test2执行之后,仍然找不到test2
,这是受以下命令行工作的启发
eval(substitute(test <- Time + weight, dat))
eval(替换(test我感觉这太复杂了。with
和in
都返回由数据帧的命名列上的操作计算的值。如果不将它们分配给任何对象,该值将被垃圾收集。存储tehn的常用方法是分配给命名对象,或者可能是带有的对象很有用,但中的比带有的的对象通用性要差得多,我很好奇为什么它需要有一个单独的函数。具体来说,
中的通过数据[nl]分配给data.frame的特定列建议是错误的。
中的没有分配到其环境之外的列。您需要这样做:dat$test2是的,您是对的。我在手机上写下了我的原始答案,无法充分阐述。答案很好,很有帮助,但仍然不能真正解决分配问题。也许答案是,“不可能--放弃你的白日梦?”:-)你可以在
中编写一个类似于的函数,但不必像第一个参数那样使用列表,而是使用一个变量名。然后该函数可以在调用环境中提取绑定到该变量名的值(使用get
),在对内部的调用中使用该值,然后使用assign
将结果分配给调用环境中的同一个变量名。我可能应该补充一点,在我看来,使用这样一个执行非局部赋值的函数作为副作用是一个非常糟糕的主意。不过,有趣的是,它是可以做到的MPE不会修改dat
,因为dat
不是一个环境。充其量只能通过as.environment
将其强制到一个环境中,进行修改,然后立即丢弃,因为没有对它的其他引用,保持原始dat
不变。
library(datasets)
library(dplyr)
library(magrittr)
dat <- as.data.frame(ChickWeight)
dat %<>% mutate(test1 = Time + weight)
dat <- dat %>% mutate(test1 = Time + weight)
dat <- mutate(dat, test1 = Time + weight)
eval(substitute(test <- Time + weight, dat))
myWith <- function(DAT, expr) {
X <- call("eval",
call("substitute", substitute(expr), DAT))
eval(X, parent.frame())
}
## Trying it out
dat <- as.data.frame(ChickWeight)
myWith(dat, test <- Time + weight)
head(test)
# [1] 42 53 63 70 84 103
dat <- within(dat, newcol <- oldcol1*oldcol2)
dat$newcol <- with(dat, oldcol1*oldcol2)