R 获取到矩阵中非零邻居的距离
有谁能告诉我一个聪明的方法,如何计算到稀疏矩阵中非零邻居的距离?这样做的原因是,我想确定一个大型多维矩阵中的“漏洞” 举个例子:假设我有一个10x10的矩阵,里面有很多零和一些1:R 获取到矩阵中非零邻居的距离,r,matrix,sparse-matrix,R,Matrix,Sparse Matrix,有谁能告诉我一个聪明的方法,如何计算到稀疏矩阵中非零邻居的距离?这样做的原因是,我想确定一个大型多维矩阵中的“漏洞” 举个例子:假设我有一个10x10的矩阵,里面有很多零和一些1: f<-ceiling((runif(100,0,1))-.6) a <- matrix(f, ncol=10L, nrow=10L) rownames(a) = seq(1,10,1) colnames(a) = seq(1,10,1) 因此,我需要的是一个10x10矩阵,所有零点的所有四个方向的平均距
f<-ceiling((runif(100,0,1))-.6)
a <- matrix(f, ncol=10L, nrow=10L)
rownames(a) = seq(1,10,1)
colnames(a) = seq(1,10,1)
因此,我需要的是一个10x10矩阵,所有零点的所有四个方向的平均距离(每个维度两个)
例如,点a[6,5]
为零,有4个相邻点。左侧距离为5,右侧距离为1,向上距离为3,向下距离为1。所以平均值是2,5。如果邻居不存在,则应计算剩余邻居的平均值
和往常一样,我的第一个想法是一组for循环,在各个方向上查找每个矩阵值并返回距离。但是这一定是最愚蠢的方法了…对于你的矩阵,你可以用
转换成稀疏的r x c形式,其中:
rc <- which(a>0, arr.ind=TRUE)
rc[rc[,1] == 6, 2] # 1, 6,8 candidates for "row-neighbors"
rc[rc[,2] == 5, 1] # 1,2,3, 7,8,10 col-neighbors
rc 0,arr.ind=TRUE)
rc[rc[,1]==6,2]#1,6,8“行邻居”的候选对象
rc[rc[,2]==5,1]#1,2,3,7,8,10
我非常喜欢这个问题!这里有一个解决方案,不一定是快速的,但它确实有效
首先,让我们重新创建您的数据:
a <- matrix(scan(textConnection("
0 0 0 0 1 0 0 1 1 0
1 0 0 0 1 0 0 0 0 0
0 1 1 0 1 1 0 0 1 1
0 0 1 1 0 1 0 1 0 0
0 0 0 1 0 1 0 0 0 1
1 0 0 0 0 1 0 1 0 0
0 1 1 1 1 1 1 0 1 0
1 0 1 0 1 0 0 0 1 1
1 1 1 0 0 0 0 0 0 0
1 1 1 1 1 0 1 0 1 0
")), 10, 10, byrow = TRUE)
在你的例子中,我认为到左边的距离是4,而不是5。我确实认为你需要一些函数,如apply
或outer
,以至少隐式循环10 x 10范围。当然你是对的,大卫。这看起来令人印象深刻,非常感谢你的努力,弗洛德尔。我会检查一下,让你知道它是否对我原来的问题有效。“邻居的候选人是一个不错的中间结果。我也会试试这个。谢谢你,德温!
a <- matrix(scan(textConnection("
0 0 0 0 1 0 0 1 1 0
1 0 0 0 1 0 0 0 0 0
0 1 1 0 1 1 0 0 1 1
0 0 1 1 0 1 0 1 0 0
0 0 0 1 0 1 0 0 0 1
1 0 0 0 0 1 0 1 0 0
0 1 1 1 1 1 1 0 1 0
1 0 1 0 1 0 0 0 1 1
1 1 1 0 0 0 0 0 0 0
1 1 1 1 1 0 1 0 1 0
")), 10, 10, byrow = TRUE)
rev.list <- function(l) lapply(l, rev)
v1 <- split(a, row(a)) # rows left to right
v2 <- rev.list(v1) # rows right to left
v3 <- split(a, col(a)) # cols up to down
v4 <- rev.list(v3) # cols down to up
dir.dist <- function(v) {
out <- seq_along(v) - cummax(seq_along(v) * v)
out[seq_len(match(1, v) - 1)] <- NA
out
}
dist1.list <- lapply(v1, dir.dist) # dist to closest on left
dist2.list <- lapply(v2, dir.dist) # dist to closest on right
dist3.list <- lapply(v3, dir.dist) # dist to closest up
dist4.list <- lapply(v4, dir.dist) # dist to closest dn
nr <- nrow(a)
nc <- ncol(a)
list.to.mat <- function(l, revert = FALSE, byrow = FALSE,
nrow = nr, ncol = nc) {
x <- unlist(if (revert) rev.list(l) else l)
matrix(x, nrow, ncol, byrow)
}
m1 <- list.to.mat(dist1.list, revert = FALSE, byrow = TRUE)
m2 <- list.to.mat(dist2.list, revert = TRUE, byrow = TRUE)
m3 <- list.to.mat(dist3.list, revert = FALSE, byrow = FALSE)
m4 <- list.to.mat(dist4.list, revert = TRUE, byrow = FALSE)
pmean <- function(..., na.rm = FALSE) {
dat <- do.call(cbind, list(...))
res <- rowMeans(dat, na.rm = na.rm)
idx_na <- !rowSums(!is.na(dat))
res[idx_na] <- NA
res
}
final <- matrix(pmean(as.vector(m1),
as.vector(m2),
as.vector(m3),
as.vector(m4), na.rm = TRUE), nr, nc)
final
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] 2.50 2.50 2.00 2.00 0.00 1.67 3.00 0.0 0.00 1.50
# [2,] 0.00 1.67 1.67 2.00 0.00 1.00 3.50 2.0 2.00 3.00
# [3,] 1.67 0.00 0.00 1.00 0.00 0.00 2.33 1.5 0.00 0.00
# [4,] 2.00 1.67 0.00 0.00 1.50 0.00 1.67 0.0 1.67 1.33
# [5,] 2.33 2.00 1.33 0.00 1.50 0.00 2.00 1.5 2.00 0.00
# [6,] 0.00 2.25 2.00 1.75 *2.25* 0.00 1.00 0.0 1.67 1.67
# [7,] 1.00 0.00 0.00 0.00 0.00 0.00 0.00 1.0 0.00 1.33
# [8,] 0.00 1.00 0.00 1.25 0.00 1.67 1.75 2.0 0.00 0.00
# [9,] 0.00 0.00 0.00 1.33 1.33 2.50 2.33 4.0 2.67 4.00
# [10,] 0.00 0.00 0.00 0.00 0.00 1.67 0.00 2.0 0.00 1.50