微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么子集这个数据框会改变它的以前重复的列名?

如何解决为什么子集这个数据框会改变它的以前重复的列名?

考虑

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(`[`)

返回一堆方法,其中一个是 [.data.frame,它执行检查名称并使用从 names 获得的唯一名称分配 make.unique

`[.data.frame`
...
...
if (has.j && anyDuplicated(nm <- names(x))) 
        names(x) <- make.unique(nm)
...

使用 [,传递的参数只有 ijdrop 以及对象 '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

注意:建议不要在 matrixdata.frame 中使用重复的列名,因为这可能会在代码中造成不必要的错误

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。