Home > Mobile >  Why can names(x) be NULL, but colnames(x) are not?
Why can names(x) be NULL, but colnames(x) are not?

Time:12-22

From the docs ?name:

names(x)
...
x an R object.
...
(NULL is given if the object has no names, including for objects of types which cannot have names.)

But consider the following example:

tbl <- table(data.frame(x=c(1, 2), y=c(3, 4)))
names(tbl)
# NULL
colnames(tbl)
# [1] "3" "4"

My understanding is that this does not fit the documentation, or am I missing something?
The docs also state that "The default methods get and set the "names" attribute of a vector (including a list) or pairlist."
But then it should either return an error for a data.frame or the correct colnames and / rownames or both?


What I thought about:

x <- c(1:3)
names(x) <- letters[1:3]
df <- data.frame(x=c(1, 2), y=c(3, 4))
tbl <- table(df)

mynames <- function(x) { # cannot use names(x), as names(x) calls .Primitive("names")
  UseMethod("mynames")
}

mynames.integer <- function(x) {
  return(names(x))
}

mynames.table <- function(x) {
  if (is.null(names(x))) {
    r <- list(colnames = colnames(x), rownames = rownames(x))
  } else {
    r <- list(names = names(x), colnames = colnames(x), rownames = rownames(x))
  }
  return(r)
}

mynames.data.frame <- function(x) {
  return(list(colnames = colnames(x), rownames = rownames(x)))
}

mynames(x)
# [1] "a" "b" "c"
mynames(df)
# $colnames
# [1] "3" "4"
# $rownames
# [1] "1" "2"
mynames(tbl)
# $colnames
# [1] "3" "4"
# $rownames
# [1] "1" "2"

names(tbl) <- letters[1:4]
mynames(tbl)
# $names
# [1] "a" "b" "c" "d"
# $colnames
# [1] "3" "4"
# $rownames
# [1] "1" "2"

But

attributes(tbl)
# $dim
# [1] 2 2
# $dimnames
# $dimnames$x
# [1] "1" "2"
# $dimnames$y
# [1] "3" "4"
# $class
# [1] "table"

CodePudding user response:

It is based on the idea that data in R is a vector with attributes and the names are the names on that vector.

A data frame is a vector/list of columns so its names are the column names.

However, a table is not a list of columns. It is a vector of cells and we know its structure from the dim and dimnames attributes so its names are the names of the individual cells. tbl shown in the question does not have names on the individual cells but we could add names.

names(tbl) <- letters[1:4]

tbl # this does not actually show the names but they are there
##    y
## x   3 4
##   1 1 0
##   2 0 1

tbl[3]
## c   <--------------------
## 0 

c(tbl) 
## a b c d <--------------------
## 1 0 0 1 
  •  Tags:  
  • r
  • Related