[英]Accessing a certain range of matrix elements in R
我有一個矩陣,我想要將某些特定元素歸零。
例如,假設我的矩陣是:
m <- matrix(1:100, ncol=10)
然后我有兩個向量指示要保留哪些元素
m.from <- c(2, 5, 4, 4, 6, 3, 1, 4, 2, 5)
m.to <- c(7, 9, 6, 8, 9, 5, 6, 8, 4, 8)
因此,舉例來說,我將第1行中的元素3:6保留,並將元素1:2和7:10設置為0.對於第2行,我將保持6:8,其余為零,依此類推。
現在,我可以輕松地做到:
for (line in 1:nrow(m))
{
m[line, 1:m.from[line]] <- 0
m[line, m.to[line]:ncol(m)] <- 0
}
這給出了正確的結果。
然而,在我的特定情況下,我在~15000 x 3000矩陣上操作,這使得使用這種環路的時間非常長。
我怎樣才能加快這段代碼的速度? 我雖然使用apply
,但是如何訪問m.from和m.to的正確索引?
這是一個簡單的面向矩陣的解決方案:
m[col(m) <= m.from] <- 0
m[col(m) >= m.to] <- 0
m
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 0 0 21 31 41 51 0 0 0 0
[2,] 0 0 0 0 0 52 62 72 0 0
[3,] 0 0 0 0 43 0 0 0 0 0
[4,] 0 0 0 0 44 54 64 0 0 0
[5,] 0 0 0 0 0 0 65 75 0 0
[6,] 0 0 0 36 0 0 0 0 0 0
[7,] 0 17 27 37 47 0 0 0 0 0
[8,] 0 0 0 0 48 58 68 0 0 0
[9,] 0 0 29 0 0 0 0 0 0 0
[10,] 0 0 0 0 0 60 70 0 0 0
(我想我也可能在這一場比賽中贏得R高爾夫獎。)我的參賽作品將是:
m[col(m)<=m.from|col(m)>= m.to]<-0
最好的解決方案是預先計算要替換的所有索引,然后用單個賦值操作替換它們。
由於R以列為主要順序存儲矩陣,因此我發現在矩陣的轉置版本中更容易考慮要替換的元素序列。 這就是我在下面使用的內容。 但是,如果對t()
的兩次調用成本太高,我相信你可以找出一種聰明的方法來計算未轉換矩陣的索引 - 也許使用包含行和列索引的兩列矩陣。
## Your example
m <- matrix(1:100, ncol=10)
m.from <- c(2, 5, 4, 4, 6, 3, 1, 4, 2, 5)
m.to <- c(7, 9, 6, 8, 9, 5, 6, 8, 4, 8)
## Let's work with a transposed version of your matrix
tm <- t(m)
## Calculate indices of cells to be replaced
i <- (seq_len(ncol(tm)) - 1) * nrow(tm)
m.to <- c(1, m.to + i)
m.from <- c(m.from + i, length(m))
ii <- unlist(mapply(seq, from = m.to, to = m.from))
## Perform replacement and transpose back results
tm[ii] <- 0
m <- t(tm)
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] 0 0 21 31 41 51 0 0 0 0
# [2,] 0 0 0 0 0 52 62 72 0 0
# [3,] 0 0 0 0 43 0 0 0 0 0
# [4,] 0 0 0 0 44 54 64 0 0 0
# [5,] 0 0 0 0 0 0 65 75 0 0
# [6,] 0 0 0 36 0 0 0 0 0 0
# [7,] 0 17 27 37 47 0 0 0 0 0
# [8,] 0 0 0 0 48 58 68 0 0 0
# [9,] 0 0 29 0 0 0 0 0 0 0
# [10,] 0 0 0 0 0 60 70 0 0 0
一個sapply
版本。
m <- matrix(1:100, ncol=10)
m.from <- c(2, 5, 4, 4, 6, 3, 1, 4, 2, 5)
m.to <- c(7, 9, 6, 8, 9, 5, 6, 8, 4, 8)
t(sapply(1:nrow(m), function(i) replace(m[i,], c(1:m.from[i], m.to[i]:ncol(m)), 0 )))
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 0 0 21 31 41 51 0 0 0 0
[2,] 0 0 0 0 0 52 62 72 0 0
[3,] 0 0 0 0 43 0 0 0 0 0
[4,] 0 0 0 0 44 54 64 0 0 0
[5,] 0 0 0 0 0 0 65 75 0 0
[6,] 0 0 0 36 0 0 0 0 0 0
[7,] 0 17 27 37 47 0 0 0 0 0
[8,] 0 0 0 0 48 58 68 0 0 0
[9,] 0 0 29 0 0 0 0 0 0 0
[10,] 0 0 0 0 0 60 70 0 0 0
經過的時間尚未測試
此選項構造一個要替換的雙列矩陣索引元素,並且不需要矩陣轉置,因此應該很難超越
## Your data
m <- matrix(1:100, ncol=10)
m.from <- c(2, 5, 4, 4, 6, 3, 1, 4, 2, 5)
m.to <- c(7, 9, 6, 8, 9, 5, 6, 8, 4, 8)
## Construct a two column matrix with row (ii) and column (jj) indices
## of cells to be replaced
ii <- rep.int(1:ncol(m), times = (m.from + (ncol(m) - m.to + 1)))
jj <- mapply(seq, from = m.from + 1, to = m.to - 1)
jj <- unlist(sapply(jj, function(X) setdiff(1:10,X)))
ij <- cbind(ii, jj)
## Replace cells
m[ij] <- 0
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] 0 0 21 31 41 51 0 0 0 0
# [2,] 0 0 0 0 0 52 62 72 0 0
# [3,] 0 0 0 0 43 0 0 0 0 0
# [4,] 0 0 0 0 44 54 64 0 0 0
# [5,] 0 0 0 0 0 0 65 75 0 0
# [6,] 0 0 0 36 0 0 0 0 0 0
# [7,] 0 17 27 37 47 0 0 0 0 0
# [8,] 0 0 0 0 48 58 68 0 0 0
# [9,] 0 0 29 0 0 0 0 0 0 0
# [10,] 0 0 0 0 0 60 70 0 0 0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.