代码之家  ›  专栏  ›  技术社区  ›  J. Mini

为什么对该数据帧进行子集设置会更改其(以前重复的)列名?

  •  1
  • J. Mini  · 技术社区  · 4 年前

    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
    

    如我们所见,最后一列的名称被更改了。为什么?

    1 回复  |  直到 4 年前
        1
  •  1
  •   akrun    4 年前

    代码中发生了两件事。OP重写了列名的默认检查 check.names = FALSE 在构建数据框,这允许重复的列名,因为如果为TRUE,则触发的事件链将是正在调用的以下函数

     make.names -> make.unique
    

    make.unique 默认情况下,附加 .

    make.unique(rep("danger", 2))
    #[1] "danger"   "danger.1"
    

    duplicate 在中不建议使用列名 data.frame . 所以,当我们用 [ ,对的提取方法的调用数据框正在制作

    methods(`[`)
    

    返回一堆方法,其中一个是 [.data.frame 检查姓名并分配 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
    

    矩阵 因为这可能会在代码中产生不必要的错误