[英]A fast way to rank each column in a sparse matrix
我有一個dgCMatrix
稀疏矩陣:
library(Matrix)
set.seed(1)
mat <- Matrix(c(0,0,2:0), 3,5)
rownames(mat) <- paste0("g",1:3)
colnames(mat) <- paste0("c",1:5)
我想以dplyr::dense_rank()
的方式對每一列進行降序排列,這樣領帶就會獲得相同的排名,沒有差距。
我正在尋找的 output 是一個data.frame
,其中每一行都有mat
的colnames
、 rownames
和rank
s。
我目前正在使用這個do.call
function:
library(dplyr)
df <- do.call(rbind,lapply(1:ncol(mat),function(x){
data.frame(cell=colnames(mat)[x],gene_name = rownames(mat),value=mat[,x]) %>%
dplyr::arrange(desc(value)) %>%
dplyr::mutate(rank=dplyr::dense_rank(desc(value)))
}))
但是尋找更快的東西。 我知道我的問題與這篇文章類似但不完全相同,因為這篇文章中使用的split
不保留rownames
。
從CsparseMatrix
到TsparseMatrix
並對結果進行操作在這里可能是最自然的:
library(Matrix)
set.seed(0)
m <- 6L
n <- 6L
x <- rsparsematrix(m, n, 0.5, rand.x = function(n) trunc(rnorm(n, 0, 2)))
dimnames(x) <- list(paste0("r", seq_len(m)), paste0("c", seq_len(n)))
x
6 x 6 sparse Matrix of class "dgCMatrix"
c1 c2 c3 c4 c5 c6
r1 0 -1 . -2 . 1
r2 . . -1 . 0 .
r3 . -2 . 0 0 .
r4 -2 1 . 0 . 0
r5 . 0 . 0 . .
r6 . . -1 2 . 0
denseRank <- function(x, ...) match(x, sort(unique(x), ...))
y <- as(x, "TsparseMatrix")
d <- data.frame(row = y@Dimnames[[1L]][y@i+1L],
col = y@Dimnames[[2L]][y@j+1L],
val = y@x,
ran = unsplit(lapply(split(y@x, y@j), denseRank, decreasing = TRUE, na.last = NA), y@j))
d
row col val ran
1 r1 c1 0 1
2 r4 c1 -2 2
3 r1 c2 -1 3
4 r3 c2 -2 4
5 r4 c2 1 1
6 r5 c2 0 2
7 r2 c3 -1 1
8 r6 c3 -1 1
9 r1 c4 -2 3
10 r3 c4 0 2
11 r4 c4 0 2
12 r5 c4 0 2
13 r6 c4 2 1
14 r2 c5 0 1
15 r3 c5 0 1
16 r1 c6 1 1
17 r4 c6 0 2
18 r6 c6 0 2
z <- y
z@x <- as.double(d$ran)
z
6 x 6 sparse Matrix of class "dgTMatrix"
c1 c2 c3 c4 c5 c6
r1 1 3 . 3 . 1
r2 . . 1 . 1 .
r3 . 4 . 2 1 .
r4 2 1 . 2 . 2
r5 . 2 . 2 . .
r6 . . 1 1 . 2
如果矩陣包含NA
,則需要小心。 以上將na.last = NA
傳遞給denseRank
,以便NA
值獲得NA
排名; 這與dplyr::dense_rank
一致。 如果您希望為NA
值分配最低或最高等級,則必須分別傳遞na.last = FALSE
或na.last = TRUE
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.