灵感来自Q6437164:有人可以向我解释为什么以下工作:
iriscopy<-iris #or whatever other data.frame
iriscopy$someNonExistantColumn[1]<-15
Run Code Online (Sandbox Code Playgroud)
对我而言,似乎并不明白R如何将此语句解释为:someNonExistantColumn
在data.frame中创建一个名为new的新列,并将第一个值(实际上是所有值,如图所示)设置为值15.
Rei*_*son 10
R语言定义手册为我们提供了一个指针,指向R如何计算表单的表达式:
x$foo[1] <- 15
Run Code Online (Sandbox Code Playgroud)
就好像我们打电话一样
`*tmp*` <- x
x <- "$<-.data.frame"(`*tmp*`, name = "foo",
value = "[<-.data.frame"("$.data.frame"(`*tmp*`, "foo"),
1, value = 15))
rm(`*tmp*`)
Run Code Online (Sandbox Code Playgroud)
如果我们为了说明的目的而放弃使用的实际方法,那么中间位可能更容易解决:
x <- "$<-"(`*tmp*`, name = "foo",
value = "[<-"("$"(`*tmp*`, "foo"), 1, value = 15))
Run Code Online (Sandbox Code Playgroud)
回到你的例子iris
,我们有类似的东西
iris$foo[1] <- 15
Run Code Online (Sandbox Code Playgroud)
这里,递归地评估函数.第一提取功能"$"
被用于访问部件"foo"
从iris
,其是NULL
:
> "$"(iris, "foo")
NULL
Run Code Online (Sandbox Code Playgroud)
然后,"[<-"
用于替换上面返回的对象的第一个元素(the NULL
)与值15
,即调用:
> "[<-"(NULL, 1, value = 15)
[1] 15
Run Code Online (Sandbox Code Playgroud)
现在,这是在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
Run Code Online (Sandbox Code Playgroud)
(此处包含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.
Run Code Online (Sandbox Code Playgroud)
关键位是最后一句.在上面的示例中,使用了最外面的分配value = 15
.但是在这一点上,我们想要更换整个组件"foo"
,这个组件很长nrow(iris)
.因此,value = rep(15, nrow(iris))
在最外面的赋值/函数调用中实际使用的是.
这个例子更复杂,因为你必须从方便符号转换
x$foo[1] <- 15
Run Code Online (Sandbox Code Playgroud)
到适当的函数调用使用"$<-"()
,"[<-"()
和"$"()
." R语言定义" 第3.4.4节中的示例使用了这个更简单的示例:
names(x)[3] <- "Three"
Run Code Online (Sandbox Code Playgroud)
评估为
`*tmp*` <- x
x <- "names<-"(`*tmp*`, value="[<-"(names(`*tmp*`), 3, value="Three"))
rm(`*tmp*`)
Run Code Online (Sandbox Code Playgroud)
因为names()
看起来像通常的函数调用,所以稍微容易理解.