R 基于邻域策略的空间聚类三维阵列

R 基于邻域策略的空间聚类三维阵列,r,multidimensional-array,cluster-analysis,spatial,R,Multidimensional Array,Cluster Analysis,Spatial,我需要使用邻域策略在3d阵列中执行空间聚类。更清楚地说:我有一个3d图像,它表示为一个稀疏的3d数组。某些实例为1,而大多数实例为0。我希望将彼此相邻的等于1的实例聚集在一起(即,如果我们将每个实例想象为一个立方体,我希望将共享一个面、一条边或一个角且等于1的实例聚集在一起) 我需要在R中这样做,因为这一步是机器学习较长管道的一部分,我正在尝试在单个环境中实现整个管道,以尽量减少头痛。 我找到了一个与当前问题稍有关联的答案。然而,在这种情况下,集群的数量是事先知道的,而在我的情况下,集群的数量可

我需要使用邻域策略在3d阵列中执行空间聚类。更清楚地说:我有一个3d图像,它表示为一个稀疏的3d数组。某些实例为1,而大多数实例为0。我希望将彼此相邻的等于1的实例聚集在一起(即,如果我们将每个实例想象为一个立方体,我希望将共享一个面、一条边或一个角且等于1的实例聚集在一起)

我需要在R中这样做,因为这一步是机器学习较长管道的一部分,我正在尝试在单个环境中实现整个管道,以尽量减少头痛。 我找到了一个与当前问题稍有关联的答案。然而,在这种情况下,集群的数量是事先知道的,而在我的情况下,集群的数量可以是从1到实例数量等于1的任何值(前提是没有实例与另一个实例相邻)

我可以为此目的编写一个函数,但这将非常耗时,而且可能效率不高,因为我认为除了寻找非零实例之外,没有其他策略可以使用,检查每个邻居实例,如果其中任何一个是非零的,那么检查它的邻居等等

由于集群步骤包含在嵌套的交叉验证循环中,您可以自己看到,我需要更高效的东西(或者可能只是用C编写的同样的东西,以便更快)

你们中有人知道有什么功能或软件包可以帮助我吗

更新

为了回答评论,我的“稀疏”数组是稀疏的,因为大多数元素都是零,而不是以稀疏格式保存。 这里是一个玩具示例(它确实是我原始数组中非零元素的裁剪,具有dim(91109,91))

更新2

我在一台Windowsx64机器上工作,RStudio 1.0.153和R版本3.4.2(短暂的夏季)

更新3

我已经尝试了@gdkrmr给出的答案,虽然它对给定的示例很有效,但它无法推广到更大、更复杂的图像。具体来说,它过度分离了我的图像中的簇,这意味着确实相互接触的体素有时会被分割成不同的簇。 您可以自己将其可视化下载并运行以下代码

读取三维图像

library(oro.nifti)
roi <- readNIfTI("image_to_cluster.nii")
roi_img <- cal_img(roi)
库(oro.nifti)
投资回报率%
{. < 2}
指定簇标签

cluster <- 1:nrow(sparse_format)
for (i in 1:nrow(sparse_format)) {
  cl_idx <- cluster[i]
  cluster[neighborhoods[, i]] <- cl_idx
}
sparse_format <- sparse_format %>%
  as_data_frame(.) %>%
  mutate(cluster_id = cluster)
cluster

您可以使用
spatstat
包来执行此操作。你需要新的 已从github创建分支
connected.pp3
,如果需要,可以安装该分支 加载
devtools
remotes
包(这里我使用
遥控器
):

库(远程)
安装github(“spatstat/spatstat”)
图书馆(spatstat)
网格和边界框

网格36 0 2 1 36
#> 102    1    0    4 102
#> 78     2    0    3  78
#> 63     2    2    2  63
#> 88     2    2    3  88
#> 16     0    3    0  16
#> 77     1    0    3  77
#> 82     1    1    3  82
#> 53     2    0    2  53
#> 116    0    3    4 116
#> 106    0    1    4 106
#> 29     3    0    1  29
#> 52     1    0    2  52
#> 104    3    0    4 104
#> 107    1    1    4 107
#> 13     2    2    0  13
#> 51     0    0    2  51
#> 60     4    1    2  60
转换为三维点模式并查找连接的零部件(返回为 所谓的点标记)。正如@gdkrmr所指出的,任何一点 距离小于2表示邻居(这里我们使用1.8,但不使用任何值) 在sqrt(3)和2之间(应起作用)

x1429
#> 19          2       51
#> 15          2       52
#> 11          2       53
#> 20          2       60
#> 6           2       63
#> 9           2       77
#> 5           2       78
#> 10          2       82
#> 7           2       88
#> 4           2      102
#> 16          2      104
#> 13          2      106
#> 17          2      107
#> 12          2      116
#> 2           2      117
#> 8           3       16
#> 3           3       36
#> 18          4       13

这是一个纯R解决方案,它利用了相邻体素的最大距离
sqrt(d)<2
如果
d%
其中(,arr.ind=TRUE)
社区%
距离%>%
as.matrix%>%
{. < 2}

n 1)如果性能对您很重要,您可以使用
Rcpp
软件包。2) 使用索引上的
dist
功能应在3d阵列中工作,距离
<2
的每两个点应为相邻点,但这将停止对
d>3
工作。3) 我还猜想,如果对3d数组的索引进行排序,您的算法可以快几个数量级。谢谢您的评论。你对我来说有点太快了:1-我看了Rcpp软件包,我不确定如何将其用于我的目标。2 -感谢提示3 -你是什么意思3点?1)你将使用RCPP实现自己的算法在C/C++ + RCPP只是使接口C++和R更容易。3) 如果您实现自己的算法并知道索引已排序,则无需将所有点与所有点进行比较,即在1D情况下:如果索引或您的索引为:
c(1,3,4,5)
,在只检查前两个元素后,前两个元素不是邻居。一个问题:数组是以稀疏格式保存的,还是一个密集的数组,在很大程度上是由零组成的稀疏数组?这就是为什么您应该始终提供一个可复制的示例。我已经更新了问题以回答@gdkrmr问题,并添加了一个可复制的示例谢谢您的回答。安装
spatstat
的开发人员版本时遇到问题。我已经安装了
remotes
软件包,但是当我运行comand
install\u github(“spatstat/spatstat”,ref=“connected.pp3”时
array_img <- roi@.Data
sparse_format <- (array_img > 0) %>%
  which(., arr.ind = TRUE)
neighborhoods <- sparse_format %>%
  dist %>%
  as.matrix %>%
  {. < 2}
cluster <- 1:nrow(sparse_format)
for (i in 1:nrow(sparse_format)) {
  cl_idx <- cluster[i]
  cluster[neighborhoods[, i]] <- cl_idx
}
sparse_format <- sparse_format %>%
  as_data_frame(.) %>%
  mutate(cluster_id = cluster)
new_img <- roi
new_img@.Data <- array(0,c(74,92,78))

for (cl in cluster) {
  new_img@.Data[sparse_format %>% filter(., cluster_id == cl) %>% select(dim1,dim2,dim3) %>% as.matrix] <- cl
}
writeNIfTI(new_img, "test", verbose=TRUE)
library(rgl)
library(magrittr)
sparse_format <- (sparse_array > 0) %>%
  which(., arr.ind = TRUE)
neighborhoods <- sparse_format %>%
  dist %>%
  as.matrix %>%
  {. < 2}
n <- nrow(sparse_format)

perm <- 1:n
for (i in 1:n) {
  perm[i:n] <- perm[i:n][
    order(neighborhoods[perm[i], perm][i:n], 
          decreasing = TRUE)
  ]
}
neighborhoods <- neighborhoods[perm, perm]
sparse_format <- sparse_format[perm, ]

cluster <- 1:n
for (i in 1:n) {
  cl_idx <- cluster[i]
  cluster[neighborhoods[, i]] <- cl_idx
}
plot3d(sparse_format, col = cluster)