受Q6437164的启发:有人可以向我解释为什么以下有效:
iriscopy<-iris #or whatever other data.frame
iriscopy$someNonExistantColumn[1]<-15
对我来说,似乎并不明显R如何将此语句解释为:在data.frame中创建一个名为someNonExistantColumn
的新列,并设置第一个值(事实上,所有值,如图所示)值15。
答案 0 :(得分:10)
R语言定义手册为我们提供了一个指针,指向R如何计算表单的表达式:
x$foo[1] <- 15
即好像我们已经打电话了
`*tmp*` <- x
x <- "$<-.data.frame"(`*tmp*`, name = "foo",
value = "[<-.data.frame"("$.data.frame"(`*tmp*`, "foo"),
1, value = 15))
rm(`*tmp*`)
如果我们为了说明的目的而放弃使用的实际方法,那么中间位可能更容易解决:
x <- "$<-"(`*tmp*`, name = "foo",
value = "[<-"("$"(`*tmp*`, "foo"), 1, value = 15))
要使用iris
回到您的示例,我们有类似
iris$foo[1] <- 15
这里,递归地评估函数。首先,提取器函数"$"
用于从"foo"
访问组件iris
,即NULL
:
> "$"(iris, "foo")
NULL
然后,"[<-"
用于替换上面返回的对象的第一个元素(NULL
),其值为15
,即调用:
> "[<-"(NULL, 1, value = 15)
[1] 15
现在,这是在我们调用的最外层用作参数value
的对象,即使用"$<-"
的赋值:
> head("$<-"(iris, "foo", value = 15))
Sepal.Length Sepal.Width Petal.Length Petal.Width Species foo
1 5.1 3.5 1.4 0.2 setosa 15
2 4.9 3.0 1.4 0.2 setosa 15
3 4.7 3.2 1.3 0.2 setosa 15
4 4.6 3.1 1.5 0.2 setosa 15
5 5.0 3.6 1.4 0.2 setosa 15
6 5.4 3.9 1.7 0.4 setosa 15
(此处包含在head()
中以限制显示的行数。)
希望能够解释函数如何调用进度。要处理的最后一个问题是为什么整个向量foo
设置为15? ?"$<-.data.frame"
的详细信息部分给出了答案:
Details:
....
Note that there is no ‘data.frame’ method for ‘$’, so ‘x$name’
uses the default method which treats ‘x’ as a list. There is a
replacement method which checks ‘value’ for the correct number of
rows, and replicates it if necessary.
关键位是最后一句。在上面的示例中,最外面的分配使用了value = 15
。但此时,我们希望替换整个组件"foo"
,其长度为nrow(iris)
。因此,在最外面的赋值/函数调用中实际使用的是value = rep(15, nrow(iris))
。
这个例子更加复杂,因为你必须从
的便利符号转换x$foo[1] <- 15
使用"$<-"()
,"[<-"()
和"$"()
进行正确的函数调用。 The R Language Definition的Section 3.4.4中的示例使用了这个更简单的示例:
names(x)[3] <- "Three"
评估为
`*tmp*` <- x
x <- "names<-"(`*tmp*`, value="[<-"(names(`*tmp*`), 3, value="Three"))
rm(`*tmp*`)
稍微容易理解,因为names()
看起来像是通常的函数调用。
答案 1 :(得分:3)
我认为答案是它不起作用。
我认为$newcol
是创建新列的标准行为。例如:
iris$newcol <- 1
将在iris data.frame中创建一个新列。由于矢量回收,所有值都将为1。
当表达式求值为NULL时,将触发此新列的创建。来自?$<-
:
所以我认为这里发生的是表达式求值为NULL,这会触发代码创建一个新列,然后使用向量回收来填充值。
修改强>
解析可能使用$ -assign $<-
而不是括号分配[<-
。比较:
head(`$<-`(iris, newcol, 1))
Sepal.Length Sepal.Width Petal.Length Petal.Width Species newcol
1 5.1 3.5 1.4 0.2 setosa 1
2 4.9 3.0 1.4 0.2 setosa 1
3 4.7 3.2 1.3 0.2 setosa 1
4 4.6 3.1 1.5 0.2 setosa 1
5 5.0 3.6 1.4 0.2 setosa 1
6 5.4 3.9 1.7 0.4 setosa 1
但括号分配会产生错误:
head(`[<-`(iris, newcol, 1))
Error in head(`[<-`(iris, newcol, 1)) :
error in evaluating the argument 'x' in selecting a method for function 'head': Error in is.atomic(value) : 'value' is missing