为什么对该数据框进行子集化会更改其(以前重复的)列名?
Why does subsetting this data frame change its (formerly duplicated) column names?
考虑
DF <- data.frame(
x=1:5,
y=5:1,
z=rep(5,5),
danger=11:15,
danger=12:16,
check.names = FALSE
)
drops <- c("x","z")
DF
DF[!(names(DF) %in% drops)]
有了这个,我们得到以下输出:
> DF
x y z danger danger
1 1 5 5 11 12
2 2 4 5 12 13
3 3 3 5 13 14
4 4 2 5 14 15
5 5 1 5 15 16
> DF[!(names(DF) %in% drops)]
y danger danger.1
1 5 11 12
2 4 12 13
3 3 13 14
4 2 14 15
5 1 15 16
如我们所见,最后一列的名称已更改。为什么?
代码中发生了几件事。 OP 在构造 data.frame 时用 check.names = FALSE
覆盖了对列名的默认检查,这允许重复的列名,因为如果它是 TRUE,那么触发的事件链将是以下函数被调用
make.names -> make.unique
和 make.unique
默认附加一个 .
和一个数字作为重复元素的后缀
make.unique(rep("danger", 2))
#[1] "danger" "danger.1"
duplicate
不推荐在 data.frame
中使用列名。因此,当我们使用 [
执行子集时,会调用 data.frame 的 Extract 方法
methods(`[`)
return 一堆方法,其中一个是 [.data.frame
,它检查名称并使用从 make.unique
[=33 获得的唯一名称分配给 names
=]
`[.data.frame`
...
...
if (has.j && anyDuplicated(nm <- names(x)))
names(x) <- make.unique(nm)
...
对于 [
,传递的参数只有 i
、j
和 drop
以及对象 'x'
formalArgs(`[.data.frame`)
#[1] "x" "i" "j" "drop"
因此,我们不能通过在此处传递任何 check.names
来覆盖该行为
但是,matrix
没有重复列名的问题
as.matrix(DF)[, !(names(DF) %in% drops)]
# y danger danger
#[1,] 5 11 12
#[2,] 4 12 13
#[3,] 3 13 14
#[4,] 2 14 15
#[5,] 1 15 16
注意:建议不要在 matrix
或 data.frame
中使用重复的列名,因为这可能会在代码中产生不必要的错误
考虑
DF <- data.frame(
x=1:5,
y=5:1,
z=rep(5,5),
danger=11:15,
danger=12:16,
check.names = FALSE
)
drops <- c("x","z")
DF
DF[!(names(DF) %in% drops)]
有了这个,我们得到以下输出:
> DF
x y z danger danger
1 1 5 5 11 12
2 2 4 5 12 13
3 3 3 5 13 14
4 4 2 5 14 15
5 5 1 5 15 16
> DF[!(names(DF) %in% drops)]
y danger danger.1
1 5 11 12
2 4 12 13
3 3 13 14
4 2 14 15
5 1 15 16
如我们所见,最后一列的名称已更改。为什么?
代码中发生了几件事。 OP 在构造 data.frame 时用 check.names = FALSE
覆盖了对列名的默认检查,这允许重复的列名,因为如果它是 TRUE,那么触发的事件链将是以下函数被调用
make.names -> make.unique
和 make.unique
默认附加一个 .
和一个数字作为重复元素的后缀
make.unique(rep("danger", 2))
#[1] "danger" "danger.1"
duplicate
不推荐在 data.frame
中使用列名。因此,当我们使用 [
执行子集时,会调用 data.frame 的 Extract 方法
methods(`[`)
return 一堆方法,其中一个是 [.data.frame
,它检查名称并使用从 make.unique
[=33 获得的唯一名称分配给 names
=]
`[.data.frame`
...
...
if (has.j && anyDuplicated(nm <- names(x)))
names(x) <- make.unique(nm)
...
对于 [
,传递的参数只有 i
、j
和 drop
以及对象 'x'
formalArgs(`[.data.frame`)
#[1] "x" "i" "j" "drop"
因此,我们不能通过在此处传递任何 check.names
来覆盖该行为
但是,matrix
没有重复列名的问题
as.matrix(DF)[, !(names(DF) %in% drops)]
# y danger danger
#[1,] 5 11 12
#[2,] 4 12 13
#[3,] 3 13 14
#[4,] 2 14 15
#[5,] 1 15 16
注意:建议不要在 matrix
或 data.frame
中使用重复的列名,因为这可能会在代码中产生不必要的错误