使用行名映射和用户定义的函数对矩阵进行子集化

subset a matrix using the rownames mapping and a user-defined function

我有一个矩阵,想使用映射和函数对其进行子集化。

示例:使用 runifset.seed 随机填充矩阵以实现再现性。

set.seed(1)
exp.mat <- matrix(runif(9*6, 5.0, 10), nrow = 9, ncol = 6)
rownames(exp.mat) <- c('a','b1','b2','b3','c','d1','d2','e1','e2')
colnames(exp.mat) <- c('s1','s2','s3','s4','s5','s6')

exp.mat
         s1       s2       s3       s4       s5       s6
a  5.353395 6.661973 6.733417 8.562573 6.198147 8.024666
b1 5.497331 8.254352 6.668875 6.999972 5.294672 8.273620
b2 6.581359 6.290084 7.381756 6.626761 8.211441 6.765986
b3 7.593171 7.392726 9.460992 8.785436 9.381346 6.351301
c  8.310025 8.831553 9.321697 6.013461 8.894573 9.963420
d1 7.034151 5.421235 6.949948 8.555606 8.986544 8.167466
d2 9.564380 9.376607 8.886603 5.608460 7.276372 6.066041
e1 6.468017 6.695365 9.803090 6.227443 7.050420 5.646862
e2 7.295329 9.197202 7.173297 5.716522 9.054351 7.390590

rown 列的映射包含原始矩阵的 rownames,第 map 列包含对应的映射。

maps <- data.frame(rown=c('a','b1','b2','b3','c','d1','d2','e1','e1','e1'), 
                   map =c('a','b','b','b','c','d','d','e','f','g'))
maps

   rown map
 1    a   a
 2   b1   b
 3   b2   b
 4   b3   b
 5    c   c
 6   d1   d
 7   d2   d
 8   e1   e
 9   e1   f
10   e1   g

函数,这里考虑mean用于当映射比较多时(case 2)选择行。

apply(exp.mat, 1, mean)
       a       b1       b2       b3        c       d1       d2       e1       e2 
6.922362 6.831470 6.976231 8.160829 8.555789 7.519158 7.796410 6.981866 7.637882 

根据映射,

  1. 如果 rown 中只有一个值映射到 map 那么它应该 直接复制整行。例如:a,c 只有一个映射。
  2. 如果 rown 中有多个值映射到 map 那么它 应该从上面的结果函数中复制具有最高值的整行。例如:b1b2b3 映射到 bb3 最高 mean。因此,它必须选择 b3 并且同样选择 d2.
  3. 如果 rown 中有一个值映射到中的多个值 map 那么它应该丢弃那些行。 eg: e1 有多个映射值 e,f.
  4. 如果没有映射,则丢弃该行。例如:e2没有对应的映射。

预期输出:子集矩阵

> exp.mat.trans
        s1       s2       s3       s4       s5       s6
a 5.353395 6.661973 6.733417 8.562573 6.198147 8.024666
b 7.593171 7.392726 9.460992 8.785436 9.381346 6.351301
c 8.310025 8.831553 9.321697 6.013461 8.894573 9.963420
d 9.564380 9.376607 8.886603 5.608460 7.276372 6.066041

请指教,如何有效地实现这一目标?

我已经实现了这个目测和下面的代码

exp.mat.trans <- exp.mat[c(1,4,5,7),]
rownames(exp.mat.trans) <- c('a','b','c','d')

由于没有值的转换,仅识别索引可能会有用?

# Index Subsetting
ind <- c(1,4,5,7)
exp.mat.trans2 <- exp.mat[ind,]
rownames(exp.mat.trans2) <- maps[ind, 'map']

exp.mat.transexp.mat.trans2 是一样的!

编辑

mapexp.mat 可能并不总是相同!

如果你想要一个有效的解决方案,我认为最好使用 data.tables 进行映射。如果我 运行 它,你的输入矩阵会有所不同。我找到了以下解决问题的方法:

set.seed(1)
exp.mat <- matrix(runif(9*6, 5.0, 10), nrow = 9, ncol = 6)
rownames(exp.mat) <- c('a','b1','b2','b3','c','d1','d2','e1','e2')
colnames(exp.mat) <- c('s1','s2','s3','s4','s5','s6')
> exp.mat
         s1       s2       s3       s4       s5       s6
a  6.327543 5.308931 6.900176 6.911940 8.971199 8.946781
b1 6.860619 6.029873 8.887226 9.348454 5.539718 5.116656
b2 7.864267 5.882784 9.673526 6.701745 8.618555 7.386150
b3 9.541039 8.435114 6.060713 7.410401 7.056372 8.661569
c  6.008410 6.920519 8.258369 7.997829 9.104731 8.463658
d1 9.491948 8.849207 5.627775 7.467707 8.235301 7.388098
d2 9.723376 7.488496 6.336103 5.931088 8.914664 9.306047
e1 8.303989 8.588093 6.930570 9.136867 7.765182 7.190486
e2 8.145570 9.959530 5.066952 8.342334 7.648598 6.223986
maps <- data.table(rown=c('a','b1','b2','b3','c','d1','d2','e1','e1'), 
                   map =c('a','b','b','b','c','d','d','e','f'))
#RULE 2 calculate mean of each row
maps[, value := rowMeans(exp.mat)[rown]]
# aggregate such that we know which mapping should be made (RULE 2)
maps <- maps[, rown[which.max(value)], by = map]
# Delete if more mappings are made first find the number of mappings (RULE 3)
number_map <- maps[,.N, by = V1]
setkey(maps, "V1")
# Delete if more than one time a mapping is found
maps <- maps[number_map[N < 2, V1]] 
# Now subset the matrix
exp.mat.sub <- exp.mat[maps$V1[maps$V1 %in% rownames(exp.mat)],]
rownames(exp.mat.sub) <- maps[match(maps$V1, rownames(exp.mat.sub))]$map
exp.mat.sub
         s1       s2       s3       s4       s5       s6
a  6.327543 5.308931 6.900176 6.911940 8.971199 8.946781
b  9.541039 8.435114 6.060713 7.410401 7.056372 8.661569
c  6.008410 6.920519 8.258369 7.997829 9.104731 8.463658
d  9.723376 7.488496 6.336103 5.931088 8.914664 9.306047