'Extract cells values of a matrix within a circle (in R)
In a matrix I would like to select a cell having a certain value (3 in the following example) and determine the number of cells having a value of 1 and 2, within a circle centered on this cell (having the value of 3). The radius of the circle could be by example of 5 cells. How to perform it ?
> setwd("F:/")
> ##Load matrix from excel
> mat <- read.csv("test.csv", header = TRUE)
>
> ##convert from data.frame to matrix
> mat <- as.matrix(mat)
> mat
X1 X1.1 X1.2 X1.3 X1.4 X1.5 X1.6 X1.7 X1.8 X1.9 X1.10 X1.11 X1.12 X1.13
[1,] 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[2,] 1 1 1 1 1 1 2 1 1 1 1 1 1 2
[3,] 1 1 1 1 2 2 2 1 1 1 1 2 2 2
[4,] 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[5,] 1 2 1 1 1 1 1 1 2 1 1 1 1 1
[6,] 1 2 1 1 1 1 1 1 2 1 1 1 1 1
[7,] 1 2 1 1 1 1 1 1 2 1 1 2 1 1
[8,] 1 2 2 1 1 1 1 1 2 2 1 2 1 1
[9,] 1 1 1 2 1 1 1 3 1 1 1 2 1 1
[10,] 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[11,] 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[12,] 1 1 1 1 1 1 1 1 1 2 2 2 1 1
[13,] 1 1 1 1 1 1 2 1 1 1 1 1 1 2
[14,] 1 1 1 1 2 2 2 1 1 1 1 2 2 2
[15,] 1 1 1 1 2 2 2 1 1 1 1 2 2 2
[16,] 1 1 2 2 2 1 1 1 1 1 1 1 1 1
Solution 1:[1]
Example Data
A 10x10 matrix with 3 assigned to two places([1, 1]
and [5, 5]
).
mat <- matrix(sample(1:2, 10*10, TRUE), 10)
mat[1, 1] <- 3
mat[5, 5] <- 3
Find the coordinates of center cells and the area to detect the number of cells having a value of 1 and 2.
cent <- which(mat == 3, arr.ind = TRUE)
# row col
# [1,] 1 1
# [2,] 5 5
area <- arrayInd(which(mat %in% 1:2), dim(mat))
Calculate distances between centers and each cell in the detecting area, and then count the number of cells within the radius (I set 3 here)
apply(cent, 1, \(x) sum(sqrt(colSums((t(area) - x)^2)) <= 3))
# [1] 10 28
or output the coordinates of those cells directly.
apply(cent, 1, \(x) area[sqrt(colSums((t(area) - x)^2)) <= 3, ])
Solution 2:[2]
The proposed solution does not work on my computer, so I used the same idea but with a different code to calculate the distance as follow:
#Example Data
#A 10x10 matrix with 3 assigned to [5, 5]).
mat <- matrix(sample(1:2, 10*10, TRUE), 10)
mat[5, 5] <- 3
mat
#Find the coordinates of center cell having value of 3.
cent <- which(mat == 3, arr.ind = TRUE)
cent
#Find the area to detect the number of cells having a value of 1
area1 <- arrayInd(which(mat %in% 1), dim(mat))
#Find the area to detect the number of cells having a value of 2
area2 <- arrayInd(which(mat %in% 2), dim(mat))
library(raster)
#calculate distance between center and area1
distance1 <- pointDistance(cent, area1, lonlat=FALSE)
dataframe1 <- as.data.frame(distance1)
#extract only distance lower than 3
data1 <- as.data.frame(dataframe[dataframe1$distance < 3, ])
totalClass1 <- as.numeric(nrow(data1))
#calculate distance between center and area2
distance2 <- pointDistance(cent, area2, lonlat=FALSE)
dataframe2 <- as.data.frame(distance2)
#extract only distance lower than 3
data2 <- as.data.frame(dataframe[dataframe2$distance < 3, ])
totalClass2 <- as.numeric(nrow(data2))
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Laurent |