使用行名映射和用户定义的函数对矩阵进行子集化
subset a matrix using the rownames mapping and a user-defined function
我有一个矩阵,想使用映射和函数对其进行子集化。
示例:使用 runif
和 set.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
根据映射,
- 如果
rown
中只有一个值映射到 map
那么它应该
直接复制整行。例如:a
,c
只有一个映射。
- 如果
rown
中有多个值映射到 map
那么它
应该从上面的结果函数中复制具有最高值的整行。例如:b1
、b2
、b3
映射到 b
; b3
最高 mean
。因此,它必须选择 b3
并且同样选择 d2
.
- 如果
rown
中有一个值映射到中的多个值
map
那么它应该丢弃那些行。 eg: e1
有多个映射值 e
,f
.
- 如果没有映射,则丢弃该行。例如:
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.trans
和 exp.mat.trans2
是一样的!
编辑
map
和 exp.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
我有一个矩阵,想使用映射和函数对其进行子集化。
示例:使用 runif
和 set.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
根据映射,
- 如果
rown
中只有一个值映射到map
那么它应该 直接复制整行。例如:a
,c
只有一个映射。 - 如果
rown
中有多个值映射到map
那么它 应该从上面的结果函数中复制具有最高值的整行。例如:b1
、b2
、b3
映射到b
;b3
最高mean
。因此,它必须选择b3
并且同样选择d2
. - 如果
rown
中有一个值映射到中的多个值map
那么它应该丢弃那些行。 eg:e1
有多个映射值e
,f
. - 如果没有映射,则丢弃该行。例如:
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.trans
和 exp.mat.trans2
是一样的!
编辑
map
和 exp.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