R: how to get row and column names of the true elements of a matrix?

前端 未结 3 960
隐瞒了意图╮
隐瞒了意图╮ 2021-01-12 02:06

I have a logical matrix x with named rows (\'a\' and \'b\') and named columns (\'10\', \'20\', \'30\', \'40\'). Let\'s say, this:

   10   20   3         


        
相关标签:
3条回答
  • 2021-01-12 02:28

    You didn't specify this, but your desired output will require that we assume that the result is in fact rectangular. Namely, that we don't get 3 column names for a and only 2 column names for b.

    I think this should get you started, at least:

    m <- structure(c(TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE),
    .Dim = c(2L, 4L), .Dimnames = list(c("a", "b"), c("10", "20", "30", "40")))
    
    rr <- rownames(m)[row(m)[which(m)]]
    cc <- colnames(m)[col(m)[which(m)]]
    
    dd <- data.frame(rr = rr,cc = cc)
    dd
    

    which returns the information you want, but in a safer "long" format, which won't choke on the non-rectangular case. Once there, you could re-organize it as you specified like this:

    library(plyr)
    ddply(dd,.(rr),function(x){ x$cc })
    

    but frankly that last bit I find really ugly, and I wouldn't be surprised if a better solution pops up if you wait a bit.

    0 讨论(0)
  • 2021-01-12 02:28

    You can use the fact that table objects are converted to "long" format data frames by as.data.frame():

    # Create matrix of interest 
    mat <- structure(c(TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE), .Dim = c(2L, 4L), .Dimnames = list(c("a", "b"), c("10", "20", "30", "40")))
    
    # Convert to table, then to long data.frame
    df <- mat %>% as.table %>% as.data.frame(., stringsAsFactors=FALSE)
    

    The resulting df is the following:

      Var1 Var2  Freq
    1    a   10  TRUE
    2    b   10 FALSE
    3    a   20 FALSE
    4    b   20  TRUE
    5    a   30  TRUE
    6    b   30 FALSE
    7    a   40 FALSE
    8    b   40  TRUE
    

    Which you can then index to only keep TRUE rows:

    df <- df[df$Freq,1:2] %>% sort
    df
          Var1 Var2
        1    a   10
        5    a   30
        4    b   20
        8    b   40
    

    You can use dplyr to convert this into exactly the table you want:

    library(plyr)
    ddply(df, "Var1", function(x) x$Var2)
      Var1 V1 V2
    1    a 10 30
    2    b 20 40
    
    0 讨论(0)
  • 2021-01-12 02:30

    You can directly use apply.

    apply(
      x, 1, 
      function(u) paste( names(which(u)), collapse="," ) 
    )
    
    0 讨论(0)
提交回复
热议问题