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
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.
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
You can directly use apply
.
apply(
x, 1,
function(u) paste( names(which(u)), collapse="," )
)