53

Do the following function pairs generate exactly the same results?

Pair 1) names() & colnames()

Pair 2) rownames() & row.names()

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Mehper C. Palavuzlar
  • 10,089
  • 23
  • 56
  • 69

4 Answers4

81

As Oscar Wilde said

Consistency is the last refuge of the unimaginative.

R is more of an evolved rather than designed language, so these things happen. names() and colnames() work on a data.frame but names() does not work on a matrix:

R> DF <- data.frame(foo=1:3, bar=LETTERS[1:3])
R> names(DF)
[1] "foo" "bar"
R> colnames(DF)
[1] "foo" "bar"
R> M <- matrix(1:9, ncol=3, dimnames=list(1:3, c("alpha","beta","gamma")))
R> names(M)
NULL
R> colnames(M)
[1] "alpha" "beta"  "gamma"
R> 
quazgar
  • 4,304
  • 2
  • 29
  • 41
Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • Thanks for the reply with an example. So does it mean that it is always convenient to use `colnames()` instead of `names()`? Is there a similar situation for row names? – Mehper C. Palavuzlar Feb 17 '10 at 14:58
  • 2
    There are differences between data types. – Jay Feb 17 '10 at 15:03
  • 7
    Emerson said: "A foolish consistency is the hobgoblin of little minds, adored by little statesmen and philosophers and divines. With consistency a great soul has simply nothing to do." – Ken Williams Feb 17 '10 at 15:50
  • 5
    and Larry Wall said "I know it's weird, but it does make it easier to write poetry" http://groups.google.com/group/comp.lang.perl/msg/5b26830b9e52189e – JD Long Feb 17 '10 at 17:10
  • 1
    colnames DOES work on matrix, it is explicitly stated in the manual. – Tomas Dec 08 '13 at 17:20
  • @Tomas: Look at my example. I *show* that `colnames` works on both, but `names` does not. Which address the OP's point 1. – Dirk Eddelbuettel Dec 08 '13 at 18:16
  • @DirkEddelbuettel aha your example is fine, but you write *"names() and colnames() work on a data.frame but not on a matrix"* which is apparently FALSE :-) – Tomas Dec 08 '13 at 20:21
  • The AND makes it true. Both do not work on both. Only one of them does. – Dirk Eddelbuettel Dec 08 '13 at 20:49
  • 2
    @DirkEddelbuettel good programmer joke! :-)) But the fact you haven't corrected it makes me worry that you weren't joking? I guess we both know that in human language this is understood differently, as "names() work on .... AND colnames() work on ....". – Tomas Dec 09 '13 at 07:48
  • I really do not have time for this. The OP accepted the answer, 20+ people upvoted it, and *my example still stands*. If you still think you know better, I won't convince you. I already gave you two relevant answers. – Dirk Eddelbuettel Dec 09 '13 at 12:15
  • @DirkEddelbuettel I upvoted your answer, but Tomas is correct that "and" is used in the English language differently than in logic/programming. As it stands now, that sentence reads incorrectly. If you have some time, can you please make that sentence more clear? "colnames() works on both dataframes and matrices, but names() works only on dataframes." – rm999 Feb 18 '14 at 15:22
  • Efficiency is the last priority of the imaginative – Matt Nov 09 '22 at 17:26
8

Just to expand a little on Dirk's example:

It helps to think of a data frame as a list with equal length vectors. That's probably why names works with a data frame but not a matrix.

The other useful function is dimnames which returns the names for every dimension. You will notice that the rownames function actually just returns the first element from dimnames.

Regarding rownames and row.names: I can't tell the difference, although rownames uses dimnames while row.names was written outside of R. They both also seem to work with higher dimensional arrays:

>a <- array(1:5, 1:4)
> a[1,,,]
> rownames(a) <- "a"
> row.names(a)
[1] "a"
> a
, , 1, 1    
  [,1] [,2]
a    1    2

> dimnames(a)
[[1]]
[1] "a"

[[2]]
NULL

[[3]]
NULL

[[4]]
NULL
Shane
  • 98,550
  • 35
  • 224
  • 217
  • 1
    This is a better answer. Snark is funny, but knowledge is more useful. a `data.frame` indeed is usable both as a list of columns and a matrix, i.e. each column has the same length and you can extract single rows or subsets of rows. – flying sheep Feb 20 '15 at 12:01
5

I think that using colnames and rownames makes the most sense; here's why.

Using names has several disadvantages. You have to remember that it means "column names", and it only works with data frame, so you'll need to call colnames whenever you use matrices. By calling colnames, you only have to remember one function. Finally, if you look at the code for colnames, you will see that it calls names in the case of a data frame anyway, so the output is identical.

rownames and row.names return the same values for data frame and matrices; the only difference that I have spotted is that where there aren't any names, rownames will print "NULL" (as does colnames), but row.names returns it invisibly. Since there isn't much to choose between the two functions, rownames wins on the grounds of aesthetics, since it pairs more prettily withcolnames. (Also, for the lazy programmer, you save a character of typing.)

Richie Cotton
  • 118,240
  • 47
  • 247
  • 360
2

And another expansion:

# create dummy matrix
set.seed(10)
m <- matrix(round(runif(25, 1, 5)), 5)
d <- as.data.frame(m)

If you want to assign new column names you can do following on data.frame:

# an identical effect can be achieved with colnames()   
names(d) <- LETTERS[1:5]
> d
  A B C D E
1 3 2 4 3 4
2 2 2 3 1 3
3 3 2 1 2 4
4 4 3 3 3 2
5 1 3 2 4 3

If you, however run previous command on matrix, you'll mess things up:

names(m) <- LETTERS[1:5]
> m
     [,1] [,2] [,3] [,4] [,5]
[1,]    3    2    4    3    4
[2,]    2    2    3    1    3
[3,]    3    2    1    2    4
[4,]    4    3    3    3    2
[5,]    1    3    2    4    3
attr(,"names")
 [1] "A" "B" "C" "D" "E" NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA 
[20] NA  NA  NA  NA  NA  NA 

Since matrix can be regarded as two-dimensional vector, you'll assign names only to first five values (you don't want to do that, do you?). In this case, you should stick with colnames().

So there...

aL3xa
  • 35,415
  • 18
  • 79
  • 112