Find number of neighbouring values in a matrice (R) - r

My matrice is like this:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] 0 0 0 0 0 0 0 0 0
[2,] 0 0 0 0 0 0 0 0 0
[3,] 0 0 0 0 0 0 0 0 0
[4,] 0 0 0 0 0 0 0 1 1
[5,] 0 0 0 0 0 0 1 1 0
[6,] 0 0 0 0 0 1 0 0 0
[7,] 0 0 0 0 1 1 0 0 0
[8,] 0 0 0 0 1 0 0 0 0
[9,] 0 0 0 0 1 0 0 0 0
[10,] 0 0 0 0 1 1 0 0 0
[11,] 0 0 0 0 0 1 0 0 0
[12,] 0 0 0 0 0 1 1 1 1
[13,] 0 0 0 0 0 0 0 0 0
[14,] 0 0 0 0 0 0 0 0 0
[15,] 0 0 0 0 0 0 0 0 0
[16,] 0 0 0 0 0 0 0 0 0
[17,] 0 0 0 0 0 0 0 0 0
[,10] [,11] [,12] [,13] [,14] [,15] [,16] [,17]
[1,] 0 0 0 0 0 0 0 0
[2,] 0 0 0 0 0 0 0 0
[3,] 0 0 0 0 0 0 0 0
[4,] 1 1 0 0 0 0 0 0
[5,] 0 1 0 0 0 0 0 0
[6,] 0 1 0 0 0 0 0 0
[7,] 0 1 0 0 0 0 0 0
[8,] 0 1 0 0 0 1 0 0
[9,] 0 1 0 0 0 1 0 0
[10,] 1 1 0 0 0 1 0 0
[11,] 1 1 0 1 1 0 0 0
[12,] 1 1 1 1 0 0 0 0
[13,] 0 0 0 0 0 0 0 0
[14,] 0 0 0 0 0 0 0 0
[15,] 0 0 0 0 0 0 0 0
[16,] 0 0 0 0 0 0 0 0
[17,] 0 0 0 0 0 0 0 0
[,18]
[1,] 0
[2,] 0
[3,] 0
[4,] 0
[5,] 0
[6,] 0
[7,] 0
[8,] 0
[9,] 0
[10,] 0
[11,] 0
[12,] 0
[13,] 0
[14,] 0
[15,] 0
[16,] 0
[17,] 0
How can I find the number of values which has 1 in neighbour? (neighbour of a pixel is the value above the value, below the value, to the right, to the left, top right, top left, below left, below right).
I just need to get a way of devising how I can even find the number of values which has 1 above/below it. If I get that, I'll be able to solve the other variables of the problem (top right and such).
I've been experimenting around with which such as which(imageMatrix == 1, arr.ind = TRUE)[1,1]. But I cannot figure it out. (ImageMatrix is the name of the matrix)
Can anyone lend me a hand on how I can begin with the problem so I get a jump?

In the following we use the example matrix m generated reproducibly in the Note at the end.
1) Append a row and column of zeros on each end and then apply rollsum , transpose, apply it again and transpose again. Finally subtract the original matrix so that only neighbors are counted. This solution is the most compact of those here.
library(zoo)
m2 <- rbind(0, cbind(0, m, 0), 0)
t(rollsum(t(rollsum(m2, 3)), 3)) - m
## [,1] [,2] [,3] [,4] [,5]
## [1,] 2 3 5 3 2
## [2,] 3 5 6 4 2
## [3,] 2 6 5 5 2
## [4,] 2 5 2 2 1
## [5,] 1 3 2 2 1
2) A second approach is the following. It would be much faster than the others here.
nr <- nrow(m)
nc <- ncol(m)
mm <- cbind(m[, -1], 0) + m + cbind(0, m[, -nc])
rbind(mm[-1, ], 0) + mm + rbind(0, mm[-nr, ]) - m
## [,1] [,2] [,3] [,4] [,5]
## [1,] 2 3 5 3 2
## [2,] 3 5 6 4 2
## [3,] 2 6 5 5 2
## [4,] 2 5 2 2 1
## [5,] 1 3 2 2 1
3) Using loops we can write the following. It is probably the most straight forward. Note that subscripting by 0 omits that element and i %% 6 equals i if i is in 1, 2, 3, 4, 5 and equals 0 if i equals 0 or 6.
nr <- nrow(m); nr1 <- nr + 1
nc <- ncol(m); nc1 <- nc + 1
mm <- 0 * m # initialize result
for(i in seq_len(nr))
for(j in seq_len(nc))
mm[i, j] <- sum(m[seq(i-1, i+1) %% nr1, seq(j-1, j+1) %% nc1]) - m[i,j]
mm
## [,1] [,2] [,3] [,4] [,5]
## [1,] 2 3 5 3 2
## [2,] 3 5 6 4 2
## [3,] 2 6 5 5 2
## [4,] 2 5 2 2 1
## [5,] 1 3 2 2 1
Note
set.seed(123)
m <- +matrix(rnorm(25) > 0, 5)
m
## [,1] [,2] [,3] [,4] [,5]
## [1,] 0 1 1 1 0
## [2,] 0 1 1 1 0
## [3,] 1 0 1 0 0
## [4,] 1 0 1 1 0
## [5,] 1 0 0 0 0

Related

Matrix of 10x10 with the same values on principal diagonal and anti-diagonal are the same and for the otherwise is zero whit for in R

I would create in R a square matrix where the values on main diagonal and anti-diagonal is the same. It's 2. The otherwise value is 0.
I would use the function "for" but I have no idea how to apply it.
This is that i would, but the way is wrong because i must use the function "for"
a <- matrix(0 , 10,10)
diag(a) <- 2
a <- data.frame(a)
a <- as.matrix(data.frame(lapply(a , rev)))
diag(a) <- 2
colnames(a) <- NULL
a
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#> [1,] 2 0 0 0 0 0 0 0 0 2
#> [2,] 0 2 0 0 0 0 0 0 2 0
#> [3,] 0 0 2 0 0 0 0 2 0 0
#> [4,] 0 0 0 2 0 0 2 0 0 0
#> [5,] 0 0 0 0 2 2 0 0 0 0
#> [6,] 0 0 0 0 2 2 0 0 0 0
#> [7,] 0 0 0 2 0 0 2 0 0 0
#> [8,] 0 0 2 0 0 0 0 2 0 0
#> [9,] 0 2 0 0 0 0 0 0 2 0
#> [10,] 2 0 0 0 0 0 0 0 0 2
Here's possibly the quickest way to do it with a for-loop.
m <- matrix(0, 10, 10)
for(i in 0:9) m[11*i+1] <- m[10+i*9] <- 2
m
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#> [1,] 2 0 0 0 0 0 0 0 0 2
#> [2,] 0 2 0 0 0 0 0 0 2 0
#> [3,] 0 0 2 0 0 0 0 2 0 0
#> [4,] 0 0 0 2 0 0 2 0 0 0
#> [5,] 0 0 0 0 2 2 0 0 0 0
#> [6,] 0 0 0 0 2 2 0 0 0 0
#> [7,] 0 0 0 2 0 0 2 0 0 0
#> [8,] 0 0 2 0 0 0 0 2 0 0
#> [9,] 0 2 0 0 0 0 0 0 2 0
#> [10,] 2 0 0 0 0 0 0 0 0 2
This works because a matrix can be indexed with a single number representing the entries in column 1 (1:10), then column 2 (11:20) and so on. The diagonal starts at position 1 and repeats every 11 entries. The anti-diagonal starts at 10 and repeats every 9 entries.
If this is a homework assignment, your teacher will probably want you to use the [row, column] notation for subsetting and use nested for loops, so you would be safer submitting this:
m <- matrix(0, 10, 10)
for(i in 1:10) {
for(j in 1:10) {
if(i == j || i == 11 - j) {
m[i, j] <- 2
}
}
}
m
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#> [1,] 2 0 0 0 0 0 0 0 0 2
#> [2,] 0 2 0 0 0 0 0 0 2 0
#> [3,] 0 0 2 0 0 0 0 2 0 0
#> [4,] 0 0 0 2 0 0 2 0 0 0
#> [5,] 0 0 0 0 2 2 0 0 0 0
#> [6,] 0 0 0 0 2 2 0 0 0 0
#> [7,] 0 0 0 2 0 0 2 0 0 0
#> [8,] 0 0 2 0 0 0 0 2 0 0
#> [9,] 0 2 0 0 0 0 0 0 2 0
#> [10,] 2 0 0 0 0 0 0 0 0 2
Though it would be fun watching your teacher getting their head around the first version...
Created on 2022-06-08 by the reprex package (v2.0.1)

How to create a matrix from all possible combinations of 2 or more matrices?

Let's say, there are two matrices:
A <- B <- diag(3)
> A
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 1 0
[3,] 0 0 1
I want to create a new matrix AB, which consists of all the possible combinations of rows of A and B. Expected result:
> AB
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 0 0 1 0 0
[2,] 1 0 0 0 1 0
[3,] 1 0 0 0 0 1
[4,] 0 1 0 1 0 0
[5,] 0 1 0 0 1 0
[6,] 0 1 0 0 0 1
[7,] 0 0 1 1 0 0
[8,] 0 0 1 0 1 0
[9,] 0 0 1 0 0 1
How to do this efficiently? And can it be extended for more than two matrices?
You can use expand.grid() and take its output to index the matrix A and B,
x <- expand.grid(1:3,1:3)
cbind(A[x[,1],], B[x[,2],])
gives,
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 0 0 1 0 0
[2,] 0 1 0 0 1 0
[3,] 0 0 1 0 0 1
[4,] 1 0 0 1 0 0
[5,] 0 1 0 0 1 0
[6,] 0 0 1 0 0 1
[7,] 1 0 0 1 0 0
[8,] 0 1 0 0 1 0
[9,] 0 0 1 0 0 1
EDIT:
For more than two matrices, you can use a function like below,
myfun <- function(...) {
arguments <- list(...)
a <- expand.grid(lapply(arguments, function(x) 1:nrow(x)))
do.call(cbind,lapply(seq(a),function(x) { arguments[[x]][a[,x],] }))
}
out <- myfun(A,B,C)
head(out)
gives,
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 1 0 0 1 0 0 1 0 0 0
[2,] 0 1 0 1 0 0 1 0 0 0
[3,] 0 0 1 1 0 0 1 0 0 0
[4,] 1 0 0 0 1 0 1 0 0 0
[5,] 0 1 0 0 1 0 1 0 0 0
[6,] 0 0 1 0 1 0 1 0 0 0
Data:
A <- B <- diag(3)
C <- diag(4)

update cell entries based on a list of X and Y coordinates?

Say that I have a 10 x 5 matrix of zeros in matrix m
m <- matrix(0,10,5)
which looks like this
[,1] [,2] [,3] [,4] [,5]
[1,] 0 0 0 0 0
[2,] 0 0 0 0 0
[3,] 0 0 0 0 0
[4,] 0 0 0 0 0
[5,] 0 0 0 0 0
[6,] 0 0 0 0 0
[7,] 0 0 0 0 0
[8,] 0 0 0 0 0
[9,] 0 0 0 0 0
[10,] 0 0 0 0 0
now I have a list of coordinates in a matrix called xy:
x y
[1,] 3 1
[2,] 7 3
[3,] 8 1
[4,] 9 4
and I want to update the matrix by taking each row of coordinates above and adding 1 to the cell in matrix m that it refers to -- so the output would then look like this
[,1] [,2] [,3] [,4] [,5]
[1,] 0 0 0 0 0
[2,] 0 0 0 0 0
[3,] 1 0 0 0 0
[4,] 0 0 0 0 0
[5,] 0 0 0 0 0
[6,] 0 0 0 0 0
[7,] 0 0 1 0 0
[8,] 1 0 0 0 0
[9,] 0 0 0 1 0
[10,] 0 0 0 0 0
Your help is appreciated!
As long as you provide the coordinates as a matrix, 1st column specifiying row, 2nd column specifiying column, you can do:
xy = cbind(c(3,7,8,9),c(1,3,1,4))
m[xy] = 1
[,1] [,2] [,3] [,4] [,5]
[1,] 0 0 0 0 0
[2,] 0 0 0 0 0
[3,] 1 0 0 0 0
[4,] 0 0 0 0 0
[5,] 0 0 0 0 0
[6,] 0 0 0 0 0
[7,] 0 0 1 0 0
[8,] 1 0 0 0 0
[9,] 0 0 0 1 0
[10,] 0 0 0 0 0

I want to transform a forward star representation to incidence matrix

I have a forward star representation and i want to convert to to incidence matrix i wrote the code but it gave me wrong answer
FS <- data.frame(
archsNo = c(1:12),
snode = c(1,1,2,2,3,3,4,4,5,5,6,8),
enode = c(2,4,4,5,2,5,6,7,7,8,7,7))
print(FS)
archsNo snode enode
1 1 1 2
2 2 1 4
3 3 2 4
4 4 2 5
5 5 3 2
6 6 3 5
7 7 4 6
8 8 4 7
9 9 5 7
10 10 5 8
11 11 6 7
12 12 8 7
This what i have tried :
n = 8 #number of nodes
m = 12 #number of archs
incidence <- matrix(0L,nrow=n, ncol=m)
for(row in 1:n)
{
for(col in 1:m)
{
incidence[row][col] = ifelse(row == snode[col],1,ifelse(row == enode[col],-1,0))
row
snode[col]
enode[col]
}
}
incidence
This is the result :
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
[1,] 1 0 0 0 0 0 0 0 0 0 0 0
[2,] -1 0 0 0 0 0 0 0 0 0 0 0
[3,] 0 0 0 0 0 0 0 0 0 0 0 0
[4,] 0 0 0 0 0 0 0 0 0 0 0 0
[5,] 0 0 0 0 0 0 0 0 0 0 0 0
[6,] 0 0 0 0 0 0 0 0 0 0 0 0
[7,] 0 0 0 0 0 0 0 0 0 0 0 0
[8,] 0 0 0 0 0 0 0 0 0 0 0 0
for each cell if the node in the row is the starting node then it should contain 1 if end node then the cell should have -1 and else then 0 but this didn't happen
You don't index arrays in R with [row][col], you would use [row,col]. But here's an alternative way to fill the matrix easily without a loop
nodes <- max(FS$snode, FS$enode)
mm <- matrix(0, nrow=nodes, ncol=nrow(FS))
mm[cbind(FS$snode, FS$archsNo)] <- 1
mm[cbind(FS$enode, FS$archsNo)] <- -1
mm
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
# [1,] 1 1 0 0 0 0 0 0 0 0 0 0
# [2,] -1 0 1 1 -1 0 0 0 0 0 0 0
# [3,] 0 0 0 0 1 1 0 0 0 0 0 0
# [4,] 0 -1 -1 0 0 0 1 1 0 0 0 0
# [5,] 0 0 0 -1 0 -1 0 0 1 1 0 0
# [6,] 0 0 0 0 0 0 -1 0 0 0 1 0
# [7,] 0 0 0 0 0 0 0 -1 -1 0 -1 -1
# [8,] 0 0 0 0 0 0 0 0 0 -1 0 1

R : Updating a matrix given a set of indices

I have a matrix(initialized to zeros) and a set of indices. If the i'th value in indices is j, then I want to set the (j,i)th entry of the matrix to 1.
For eg:
> m = matrix(0, 10, 7)
> indices
[1] 2 9 3 4 5 1 10
And the result should be
> result
[,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,] 0 0 0 0 0 1 0
[2,] 1 0 0 0 0 0 0
[3,] 0 0 1 0 0 0 0
[4,] 0 0 0 1 0 0 0
[5,] 0 0 0 0 1 0 0
[6,] 0 0 0 0 0 0 0
[7,] 0 0 0 0 0 0 0
[8,] 0 0 0 0 0 0 0
[9,] 0 1 0 0 0 0 0
[10,] 0 0 0 0 0 0 1
I asked a somewhat related question a little while back, which used a vector instead of a matrix. Is there a similar simple solution to this problem?
## OP's example data
m = matrix(0, 10, 7)
j <- c(2, 9, 3, 4, 5, 1, 10)
## Construct a two column matrix of indices (1st column w. rows & 2nd w. columns)
ij <- cbind(j, seq_along(j))
## Use it to subassign into the matrix
m[ij] <- 1
m
# [,1] [,2] [,3] [,4] [,5] [,6] [,7]
# [1,] 0 0 0 0 0 1 0
# [2,] 1 0 0 0 0 0 0
# [3,] 0 0 1 0 0 0 0
# [4,] 0 0 0 1 0 0 0
# [5,] 0 0 0 0 1 0 0
# [6,] 0 0 0 0 0 0 0
# [7,] 0 0 0 0 0 0 0
# [8,] 0 0 0 0 0 0 0
# [9,] 0 1 0 0 0 0 0
# [10,] 0 0 0 0 0 0 1
For the record, the answer in your linked question can easily be adapted to suit this scenario too by using sapply:
indices <- c(2, 9, 3, 4, 5, 1, 10)
sapply(indices, tabulate, nbins = 10)
# [,1] [,2] [,3] [,4] [,5] [,6] [,7]
# [1,] 0 0 0 0 0 1 0
# [2,] 1 0 0 0 0 0 0
# [3,] 0 0 1 0 0 0 0
# [4,] 0 0 0 1 0 0 0
# [5,] 0 0 0 0 1 0 0
# [6,] 0 0 0 0 0 0 0
# [7,] 0 0 0 0 0 0 0
# [8,] 0 0 0 0 0 0 0
# [9,] 0 1 0 0 0 0 0
# [10,] 0 0 0 0 0 0 1
For small datasets you might not notice the performance difference, but Josh's answer, which uses matrix indexing, would definitely be much faster, even if you changed my answer here to use vapply instead of sapply.

Resources