考虑以下:
df <- data.frame(a = 1, b = 2, c = 3)
names(df[1]) <- "d" ## First method
## a b c
##1 1 2 3
names(df)[1] <- "d" ## Second method
## d b c
##1 1 2 3
Run Code Online (Sandbox Code Playgroud)
这两种方法都没有返回错误,但第一次没有更改列名,而第二次没有.
我认为它与我只在一个子集上运行的事实有关df,但为什么,例如,以下工作正常呢?
df[1] <- 2
## a b c
##1 2 2 3
Run Code Online (Sandbox Code Playgroud)
Bro*_*ieG 27
我认为发生的事情是替换到数据框会忽略从中抽取的数据框的属性.我不是100%肯定这一点,但以下实验似乎支持它:
df <- data.frame(a = 1:3, b = 5:7)
# a b
# 1 1 5
# 2 2 6
# 3 3 7
df2 <- data.frame(c = 10:12)
# c
# 1 10
# 2 11
# 3 12
df[1] <- df2[1] # in this case `df[1] <- df2` is equivalent
Run Code Online (Sandbox Code Playgroud)
哪个产生:
# a b
# 1 10 5
# 2 11 6
# 3 12 7
Run Code Online (Sandbox Code Playgroud)
注意值是如何更改的df,而不是名称.基本上,替换运算符`[<-`仅替换值.这就是名称未更新的原因.我相信这解释了所有问题.
在场景中:
names(df[2]) <- "x"
Run Code Online (Sandbox Code Playgroud)
您可以将分配视为如下(这是一个简化,有关更多详细信息,请参见文章末尾):
tmp <- df[2]
# b
# 1 5
# 2 6
# 3 7
names(tmp) <- "x"
# x
# 1 5
# 2 6
# 3 7
df[2] <- tmp # `tmp` has "x" for names, but it is ignored!
# a b
# 1 10 5
# 2 11 6
# 3 12 7
Run Code Online (Sandbox Code Playgroud)
最后一步是赋值`[<-`,它不尊重RHS的名称属性.
但在场景中:
names(df)[2] <- "x"
Run Code Online (Sandbox Code Playgroud)
您可以将赋值视为(再次,简化):
tmp <- names(df)
# [1] "a" "b"
tmp[2] <- "x"
# [1] "a" "x"
names(df) <- tmp
# a x
# 1 10 5
# 2 11 6
# 3 12 7
Run Code Online (Sandbox Code Playgroud)
注意我们如何直接分配names,而不是分配df哪些忽略属性.
df[2] <- 2
Run Code Online (Sandbox Code Playgroud)
因为我们直接分配给值而不是属性,所以这里没有问题.
编辑:根据@ AriB.Friedman的一些评论,这里是我认为正在进行的更详细的版本(注意我省略了S3发送`[.data.frame`等,为了清楚起见):
版本1 names(df[2]) <- "x"转换为:
df <- `[<-`(
df, 2,
value=`names<-`( # `names<-` here returns a re-named one column data frame
`[`(df, 2),
value="x"
) )
Run Code Online (Sandbox Code Playgroud)
版本2 names(df)[2] <- "x"转换为:
df <- `names<-`(
df,
`[<-`(
names(df), 2, "x"
) )
Run Code Online (Sandbox Code Playgroud)
另外,事实证明这是在R Inferno Section 8.2.34中记录的"(感谢@Frank):
right <- wrong <- c(a=1, b=2)
names(wrong[1]) <- 'changed'
wrong
# a b
# 1 2
names(right)[1] <- 'changed'
right
# changed b
# 1 2
Run Code Online (Sandbox Code Playgroud)