5

Suppose I have a list of matrices called Tables with colnames and without rownames.

 Tables <- list(structure(c(0.810145949194718, 0.0792559803788517, 0.189854050805282, 
0.920744019621148), .Dim = c(2L, 2L), .Dimnames = list(NULL, 
    c("e", "prod"))), structure(c(0.949326264941026, 0.24010922539329, 
0.0506737350589744, 0.75989077460671), .Dim = c(2L, 2L), .Dimnames = list(
    NULL, c("prod", "e"))))

I want the rownames to be the same as the colnames:

rownames(Tables[[1]])<- colnames(Tables[[1]])
rownames(Tables[[2]])<- colnames(Tables[[2]])

I've tried using lapply with no success

lapply(Tables, function(x) rownames(x) <- colnames(x))

I managed to do it using a for loop

for(i in 1:length(Tables)){
  rownames(Tables[[i]])<- colnames(Tables[[i]])
}

Tables # Expected result
[[1]]
              e      prod
e    0.81014595 0.1898541
prod 0.07925598 0.9207440

[[2]]
          prod          e
prod 0.9493263 0.05067374
e    0.2401092 0.75989077

Nevertheless, I want to find a way to do it using any *apply or any other function in base to avoid the for loop, but I can't succeed on this target. I read this but I can't figure out how to use any of those solutions. Any suggestion?

starball
  • 20,030
  • 7
  • 43
  • 238
Jilber Urbina
  • 58,147
  • 10
  • 114
  • 138
  • FYI, the matrices in the `Tables` object you've supplied already have matching column and row names. – Josh O'Brien Oct 01 '13 at 18:56
  • This is a simple enuff operation that I don't see anything wrong, or slow, w/ using a `for` loop – Carl Witthoft Oct 01 '13 at 18:58
  • 4
    I don't know why @Henrik deleted his answer, but I agree with him: your anonymous function in `lapply` needs to return `x`, i.e., `lapply(Tables, function(x) {rownames(x) <- colnames(x); x})`. – Roland Oct 01 '13 at 18:58
  • @JoshO'Brien thanks, I edited to supply the right (no rownames) list – Jilber Urbina Oct 01 '13 at 18:59
  • Ohh Roland you're absolutely right. :D – Jilber Urbina Oct 01 '13 at 19:01
  • @Roland, I started to doubt my answer when I realized the original Table had rownames. Had to create a new matrix to check that it worked. And I think it did... – Henrik Oct 01 '13 at 19:02
  • @Henrik unblock your answer and will mark it as correct, It works perfectly, you didnt gave the opportunity to accept it. My fault posting the wrong example – Jilber Urbina Oct 01 '13 at 19:05
  • @Jilber, I undeleted a while ago. Looks fine to me, but apparently not to the rest of you... – Henrik Oct 01 '13 at 19:06

4 Answers4

7
lapply(Tables, function(x){
  rownames(x) <- colnames(x)
  x
})

# [[1]]
#               e      prod
# e    0.81014595 0.1898541
# prod 0.07925598 0.9207440
# 
# [[2]]
#           prod          e
# prod 0.9493263 0.05067374
# e    0.2401092 0.75989077
Henrik
  • 65,555
  • 14
  • 143
  • 159
5

Another option:

for (x in Tables) 
   data.table::setattr(x, "dimnames", list(colnames(x), colnames(x))) 


[[1]]
              e      prod
e    0.81014595 0.1898541
prod 0.07925598 0.9207440

[[2]]
          prod          e
prod 0.9493263 0.05067374
e    0.2401092 0.75989077
Ricardo Saporta
  • 54,400
  • 17
  • 144
  • 178
4

R already has everything you need :-)

Tables <- Map(`rownames<-`, Tables, lapply(Tables, colnames))
flodel
  • 87,577
  • 21
  • 185
  • 223
  • 1
    This deserves more votes IMHO because it shows the power of R's functional programming as well as the cool way you can turn an operator into a customized function. – Carl Witthoft Oct 02 '13 at 11:35
1

Here's one way:

lapply(seq_along(Tables), function(i) {
    rownames(Tables[[i]]) <<- colnames(Tables[[i]])
    return(invisible())
})

...which is ugly -- use a loop instead. Or, if you do want to use lapply, try:

Tables <- lapply(Tables, function(x) {
    rownames(x) <- colnames(x)
    return(x)
})

Someone posted this earlier but they seem to have deleted their answer.

Adrian
  • 3,138
  • 2
  • 28
  • 39
  • 3
    The second one is the correct solution. The first one horribly violates principles of functional languages and goes against everything `lapply` is about, i.e., `lapply` is supposed to be a loop without side effects. – Roland Oct 01 '13 at 19:03
  • 2
    If you remove the first solution and leave the second, I'll upvote ;=) Ooops, I see @Roland and I were thinking the same thing at the same time, but I'll leave my comment to help convince you there's some agreement about that first one's badness! – Josh O'Brien Oct 01 '13 at 19:03
  • 1
    @Adrian thanks for your answer +1, and take into account Josh's comment to get another upvote. – Jilber Urbina Oct 01 '13 at 19:08
  • I agree the first one is horrible and ugly and unreadable. I was just trying to write something similar to the lapply(Tables, function(x) rownames(x) <- colnames(x)) in the original question. – Adrian Oct 01 '13 at 19:30