Is there an R function to get the “weighted” sum of neighboring values of a matrix (for varying radius)?Transforming a table of Nearest Neighbor Distances into a Matrixk-neighbors of a given matrix M x NGet neighbors of specified matrix elementFor each element in a matrix, find the sum of all of its neighborsadjacency matrix find if neighboresCreating a weighted adjacency matrix with iterationsPrecomputed matrix for fitting with scikit neighbors/radius classificationFinding the sum of degree value of a node's neighborsGetting a weighted matrix from networkConvert a DataFrame into Adjacency/Weights Matrix in R
US Passport stamped in UK for 6 months twice
Are there any well known academic philosophy forums?
How to Pin Point Large File eating space in Fedora 18
What does this symbol on the box of power supply mean?
Why colon to denote that a value belongs to a type?
Image processing: Removal of two spots in fundus images
Should breaking down something like a door be adjudicated as an attempt to beat its AC and HP, or as an ability check against a set DC?
Is the Indo-European language family made up?
In general, would I need to season a meat when making a sauce?
Is it true that cut time means "play twice as fast as written"?
How can I tell if I'm being too picky as a referee?
Who will lead the country until there is a new Tory leader?
Python program to find the most frequent letter in a text
What to do when you've set the wrong ISO for your film?
Installed Electric Tankless Water Heater - Internet loss when active
Where is the logic in castrating fighters?
Is it rude to call a professor by their last name with no prefix in a non-academic setting?
In the current era, do any wizards survive from 1372 DR?
If a person had control of every single cell of their body, would they be able to transform into another creature?
Is it possible to play as a necromancer skeleton?
What does the view outside my ship traveling at light speed look like?
the meaning of 'carry' in a novel
Simple function that simulates survey results based on sample size and probability
When and what was the first 3D acceleration device ever released?
Is there an R function to get the “weighted” sum of neighboring values of a matrix (for varying radius)?
Transforming a table of Nearest Neighbor Distances into a Matrixk-neighbors of a given matrix M x NGet neighbors of specified matrix elementFor each element in a matrix, find the sum of all of its neighborsadjacency matrix find if neighboresCreating a weighted adjacency matrix with iterationsPrecomputed matrix for fitting with scikit neighbors/radius classificationFinding the sum of degree value of a node's neighborsGetting a weighted matrix from networkConvert a DataFrame into Adjacency/Weights Matrix in R
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
I have a matrix M (say r rows and c columns) and I would like to get the "weighted" sum for each matrix element based on it's neighbors and create a new matrix M2. The word neighbor could be within a radius of 1 (which is often called the Moore neighborhood in Cellular Automata theory) or the radius could be a different than 1, say, 2, 3, etc.
For a particular cell in the matrix M, say somewhere in the middle. Let's say position (i,j); then the (i,j)th cell has "eight" neighbors given by,
(i-1, j-1), (i-1, j), (i-1, j+1), (i, j-1), (i, j+1), (i+1, j-1), (i+1, j), (i+1, j+1).
I want to create a matrix M2 that calculates the "weighted" sum of the (i,j)th cell plus its eight neighbors. The weighting is done based on the Euclidean distance between cells. So for example,
exp(-sqrt(2))*M[i-1,j-1] + exp(-1)*M[i-1,j] + exp(-sqrt(2))*M[i-1,j+1] + exp(-1)*M[i,j-1] + M[i,j] + exp(-1)*M[i,j+1] + exp(-sqrt(2))*M[i+1,j-1] + exp(-1)*M[i+1,j] + exp(-sqrt(2))*M[i+1,j+1]
The same idea is repeated for all cells (cells along the boundaries need to be treated specially since they don't necessarily have eight neighboring cells). The above idea is for radius 1 but the code I am trying to develop needs to be generic for any radius.
r <- 4
c <- 4
n <- r*c
(M <- matrix(1:n, r, c))
addresses <- expand.grid(x = 1:r, y = 1:c)
#Got this code in the same forum
z <- rbind(c(-1,0,1,-1,1,-1,0,1),c(-1,-1,-1,0,0,1,1,1))
get.neighbors <- function(rw)
# Convert to absolute addresses
z2 <- t(z + unlist(rw))
# Choose those with indices within mat
b.good <- rowSums(z2 > 0)==2 & z2[,1] <= nrow(M) & z2[,2] <= ncol(M)
M[z2[b.good,]]
apply(addresses,1 , get.neighbors) # Returns a list with neighbors
M
Essentially, M2 for radius = 1 must be the "weighted" sum of the current cell plus the neighbors. The current current cell always gets a weight of 1.
M = [ 1 5 9 13
2 6 10 14
3 7 11 15
4 8 12 16]
M2 = [ 5.033 13.803 .... ....
.... .... .... ....
.... .... .... ....
.... .... .... ....]
How do I go about getting matrix M2 in R? What about if radius for more than 1? I would like the weighting to happening inside two for loops so I can use the calculated weighted sum of the [i,j] cell further in the code closing the two for loops.
r for-loop matrix nearest-neighbor adjacency-matrix
add a comment |
I have a matrix M (say r rows and c columns) and I would like to get the "weighted" sum for each matrix element based on it's neighbors and create a new matrix M2. The word neighbor could be within a radius of 1 (which is often called the Moore neighborhood in Cellular Automata theory) or the radius could be a different than 1, say, 2, 3, etc.
For a particular cell in the matrix M, say somewhere in the middle. Let's say position (i,j); then the (i,j)th cell has "eight" neighbors given by,
(i-1, j-1), (i-1, j), (i-1, j+1), (i, j-1), (i, j+1), (i+1, j-1), (i+1, j), (i+1, j+1).
I want to create a matrix M2 that calculates the "weighted" sum of the (i,j)th cell plus its eight neighbors. The weighting is done based on the Euclidean distance between cells. So for example,
exp(-sqrt(2))*M[i-1,j-1] + exp(-1)*M[i-1,j] + exp(-sqrt(2))*M[i-1,j+1] + exp(-1)*M[i,j-1] + M[i,j] + exp(-1)*M[i,j+1] + exp(-sqrt(2))*M[i+1,j-1] + exp(-1)*M[i+1,j] + exp(-sqrt(2))*M[i+1,j+1]
The same idea is repeated for all cells (cells along the boundaries need to be treated specially since they don't necessarily have eight neighboring cells). The above idea is for radius 1 but the code I am trying to develop needs to be generic for any radius.
r <- 4
c <- 4
n <- r*c
(M <- matrix(1:n, r, c))
addresses <- expand.grid(x = 1:r, y = 1:c)
#Got this code in the same forum
z <- rbind(c(-1,0,1,-1,1,-1,0,1),c(-1,-1,-1,0,0,1,1,1))
get.neighbors <- function(rw)
# Convert to absolute addresses
z2 <- t(z + unlist(rw))
# Choose those with indices within mat
b.good <- rowSums(z2 > 0)==2 & z2[,1] <= nrow(M) & z2[,2] <= ncol(M)
M[z2[b.good,]]
apply(addresses,1 , get.neighbors) # Returns a list with neighbors
M
Essentially, M2 for radius = 1 must be the "weighted" sum of the current cell plus the neighbors. The current current cell always gets a weight of 1.
M = [ 1 5 9 13
2 6 10 14
3 7 11 15
4 8 12 16]
M2 = [ 5.033 13.803 .... ....
.... .... .... ....
.... .... .... ....
.... .... .... ....]
How do I go about getting matrix M2 in R? What about if radius for more than 1? I would like the weighting to happening inside two for loops so I can use the calculated weighted sum of the [i,j] cell further in the code closing the two for loops.
r for-loop matrix nearest-neighbor adjacency-matrix
Please don't ever includerm(list=ls())
in code posted in a question. It's akin to suggesting somebody run your code and it includes the oldformat C:
DOS command.
– r2evans
Mar 24 at 5:50
1
Thank you r2evans. I ll remember to never includerm(list=ls())
in the future.
– Ashok Krishnamurthy
Mar 24 at 7:27
add a comment |
I have a matrix M (say r rows and c columns) and I would like to get the "weighted" sum for each matrix element based on it's neighbors and create a new matrix M2. The word neighbor could be within a radius of 1 (which is often called the Moore neighborhood in Cellular Automata theory) or the radius could be a different than 1, say, 2, 3, etc.
For a particular cell in the matrix M, say somewhere in the middle. Let's say position (i,j); then the (i,j)th cell has "eight" neighbors given by,
(i-1, j-1), (i-1, j), (i-1, j+1), (i, j-1), (i, j+1), (i+1, j-1), (i+1, j), (i+1, j+1).
I want to create a matrix M2 that calculates the "weighted" sum of the (i,j)th cell plus its eight neighbors. The weighting is done based on the Euclidean distance between cells. So for example,
exp(-sqrt(2))*M[i-1,j-1] + exp(-1)*M[i-1,j] + exp(-sqrt(2))*M[i-1,j+1] + exp(-1)*M[i,j-1] + M[i,j] + exp(-1)*M[i,j+1] + exp(-sqrt(2))*M[i+1,j-1] + exp(-1)*M[i+1,j] + exp(-sqrt(2))*M[i+1,j+1]
The same idea is repeated for all cells (cells along the boundaries need to be treated specially since they don't necessarily have eight neighboring cells). The above idea is for radius 1 but the code I am trying to develop needs to be generic for any radius.
r <- 4
c <- 4
n <- r*c
(M <- matrix(1:n, r, c))
addresses <- expand.grid(x = 1:r, y = 1:c)
#Got this code in the same forum
z <- rbind(c(-1,0,1,-1,1,-1,0,1),c(-1,-1,-1,0,0,1,1,1))
get.neighbors <- function(rw)
# Convert to absolute addresses
z2 <- t(z + unlist(rw))
# Choose those with indices within mat
b.good <- rowSums(z2 > 0)==2 & z2[,1] <= nrow(M) & z2[,2] <= ncol(M)
M[z2[b.good,]]
apply(addresses,1 , get.neighbors) # Returns a list with neighbors
M
Essentially, M2 for radius = 1 must be the "weighted" sum of the current cell plus the neighbors. The current current cell always gets a weight of 1.
M = [ 1 5 9 13
2 6 10 14
3 7 11 15
4 8 12 16]
M2 = [ 5.033 13.803 .... ....
.... .... .... ....
.... .... .... ....
.... .... .... ....]
How do I go about getting matrix M2 in R? What about if radius for more than 1? I would like the weighting to happening inside two for loops so I can use the calculated weighted sum of the [i,j] cell further in the code closing the two for loops.
r for-loop matrix nearest-neighbor adjacency-matrix
I have a matrix M (say r rows and c columns) and I would like to get the "weighted" sum for each matrix element based on it's neighbors and create a new matrix M2. The word neighbor could be within a radius of 1 (which is often called the Moore neighborhood in Cellular Automata theory) or the radius could be a different than 1, say, 2, 3, etc.
For a particular cell in the matrix M, say somewhere in the middle. Let's say position (i,j); then the (i,j)th cell has "eight" neighbors given by,
(i-1, j-1), (i-1, j), (i-1, j+1), (i, j-1), (i, j+1), (i+1, j-1), (i+1, j), (i+1, j+1).
I want to create a matrix M2 that calculates the "weighted" sum of the (i,j)th cell plus its eight neighbors. The weighting is done based on the Euclidean distance between cells. So for example,
exp(-sqrt(2))*M[i-1,j-1] + exp(-1)*M[i-1,j] + exp(-sqrt(2))*M[i-1,j+1] + exp(-1)*M[i,j-1] + M[i,j] + exp(-1)*M[i,j+1] + exp(-sqrt(2))*M[i+1,j-1] + exp(-1)*M[i+1,j] + exp(-sqrt(2))*M[i+1,j+1]
The same idea is repeated for all cells (cells along the boundaries need to be treated specially since they don't necessarily have eight neighboring cells). The above idea is for radius 1 but the code I am trying to develop needs to be generic for any radius.
r <- 4
c <- 4
n <- r*c
(M <- matrix(1:n, r, c))
addresses <- expand.grid(x = 1:r, y = 1:c)
#Got this code in the same forum
z <- rbind(c(-1,0,1,-1,1,-1,0,1),c(-1,-1,-1,0,0,1,1,1))
get.neighbors <- function(rw)
# Convert to absolute addresses
z2 <- t(z + unlist(rw))
# Choose those with indices within mat
b.good <- rowSums(z2 > 0)==2 & z2[,1] <= nrow(M) & z2[,2] <= ncol(M)
M[z2[b.good,]]
apply(addresses,1 , get.neighbors) # Returns a list with neighbors
M
Essentially, M2 for radius = 1 must be the "weighted" sum of the current cell plus the neighbors. The current current cell always gets a weight of 1.
M = [ 1 5 9 13
2 6 10 14
3 7 11 15
4 8 12 16]
M2 = [ 5.033 13.803 .... ....
.... .... .... ....
.... .... .... ....
.... .... .... ....]
How do I go about getting matrix M2 in R? What about if radius for more than 1? I would like the weighting to happening inside two for loops so I can use the calculated weighted sum of the [i,j] cell further in the code closing the two for loops.
r for-loop matrix nearest-neighbor adjacency-matrix
r for-loop matrix nearest-neighbor adjacency-matrix
edited Mar 24 at 8:02
Ashok Krishnamurthy
asked Mar 24 at 5:23
Ashok KrishnamurthyAshok Krishnamurthy
1717
1717
Please don't ever includerm(list=ls())
in code posted in a question. It's akin to suggesting somebody run your code and it includes the oldformat C:
DOS command.
– r2evans
Mar 24 at 5:50
1
Thank you r2evans. I ll remember to never includerm(list=ls())
in the future.
– Ashok Krishnamurthy
Mar 24 at 7:27
add a comment |
Please don't ever includerm(list=ls())
in code posted in a question. It's akin to suggesting somebody run your code and it includes the oldformat C:
DOS command.
– r2evans
Mar 24 at 5:50
1
Thank you r2evans. I ll remember to never includerm(list=ls())
in the future.
– Ashok Krishnamurthy
Mar 24 at 7:27
Please don't ever include
rm(list=ls())
in code posted in a question. It's akin to suggesting somebody run your code and it includes the old format C:
DOS command.– r2evans
Mar 24 at 5:50
Please don't ever include
rm(list=ls())
in code posted in a question. It's akin to suggesting somebody run your code and it includes the old format C:
DOS command.– r2evans
Mar 24 at 5:50
1
1
Thank you r2evans. I ll remember to never include
rm(list=ls())
in the future.– Ashok Krishnamurthy
Mar 24 at 7:27
Thank you r2evans. I ll remember to never include
rm(list=ls())
in the future.– Ashok Krishnamurthy
Mar 24 at 7:27
add a comment |
2 Answers
2
active
oldest
votes
I think the following does the weighted sum that you want. I'll be finding the neighbours in a similar way @r2evans did.
wtd_nbrs_sum <- function(input_matrix,
radius,
weight_matrix)
temp_1 <- matrix(data = 0,
nrow = nrow(x = input_matrix),
ncol = radius)
temp_2 <- matrix(data = 0,
nrow = radius,
ncol = ((2 * radius) + ncol(x = input_matrix)))
input_matrix_modified <- rbind(temp_2,
cbind(temp_1, input_matrix, temp_1),
temp_2)
output_matrix <- matrix(nrow = nrow(x = input_matrix),
ncol = ncol(x = input_matrix))
for(i in seq_len(length.out = nrow(x = input_matrix)))
for(j in seq_len(length.out = nrow(x = input_matrix)))
row_min <- (radius + (i - radius))
row_max <- (radius + (i + radius))
column_min <- (radius + (j - radius))
column_max <- (radius + (j + radius))
neighbours <- input_matrix_modified[(row_min:row_max), (column_min:column_max)]
weighted_sum <- sum(neighbours * weight_matrix)
output_matrix[i, j] <- weighted_sum
return(output_matrix)
r <- 4
c <- 4
n <- r*c
M <- matrix(data = 1:n,
nrow = r,
ncol = c)
R <- 1
wts <- matrix(data = c(exp(x = -sqrt(x = 2)), exp(x = -1), exp(x = -sqrt(x = 2)), exp(x = -1), 1, exp(x = -1), exp(x = -sqrt(x = 2)), exp(x = -1), exp(x = -sqrt(x = 2))),
nrow = 3,
ncol = 3)
wtd_nbrs_sum(input_matrix = M,
radius = R,
weight_matrix = wts)
#> [,1] [,2] [,3] [,4]
#> [1,] 5.033856 13.80347 24.16296 23.89239
#> [2,] 8.596195 20.66391 34.43985 32.84175
#> [3,] 11.186067 24.10789 37.88383 35.43163
#> [4,] 9.748491 19.86486 30.22435 28.60703
Created on 2019-03-24 by the reprex package (v0.2.1)
Hope this helps.
Thank you @yarnabrina I am getting an errorError in neighbours * weight_matrix : non-conformable arrays
when I changeR = 2
. I see thewts
matrix is 3 x 3 forR = 1
but as R increaseswts
also increases in the weighted distance calculation. Any help is highly appreciated.
– Ashok Krishnamurthy
Mar 24 at 18:21
@AshokKrishnamurthy If radius is R, then you'll be need to update the weight matrix to a(2R+1)x(2R+1)
matrix. So, if you tryR=2
, get a5x5
matrixwts
and then runwtd_nbrs_sum(input_matrix = M, radius = R, weight_matrix = wts)
.
– yarnabrina
Mar 25 at 1:24
add a comment |
Edited to include weighted-sums.
There might be a really neat trick to doing it, but the most straight-forward (and maintainable) way is probably a simple two-for
-loop implementation.
M1 <- matrix(1:16, nr=4)
M1
# [,1] [,2] [,3] [,4]
# [1,] 1 5 9 13
# [2,] 2 6 10 14
# [3,] 3 7 11 15
# [4,] 4 8 12 16
The code:
get_neighbors <- function(M, radius = 1)
M2 <- M
M2[] <- 0
nr <- nrow(M)
nc <- ncol(M)
eg <- expand.grid((-radius):radius, (-radius):radius)
eg$wt <- exp(-sqrt(abs(eg[,1]) + abs(eg[,2])))
for (R in seq_len(nr))
for (C in seq_len(nc))
ind <- cbind(R + eg[,1], C + eg[,2], eg[,3])
ind <- ind[ 0 < ind[,1] & ind[,1] <= nr &
0 < ind[,2] & ind[,2] <= nc,, drop = FALSE ]
M2[R,C] <- sum(M[ind[,1:2, drop=FALSE]] * ind[,3])
M2
get_neighbors(M1, 1)
# [,1] [,2] [,3] [,4]
# [1,] 5.033856 13.80347 24.16296 23.89239
# [2,] 8.596195 20.66391 34.43985 32.84175
# [3,] 11.186067 24.10789 37.88383 35.43163
# [4,] 9.748491 19.86486 30.22435 28.60703
The same thing, with radius 2:
get_neighbors(M1, 2)
# [,1] [,2] [,3] [,4]
# [1,] 12.44761 25.64963 31.73247 32.70974
# [2,] 18.57765 35.96237 43.33862 43.51911
# [3,] 20.09836 37.80643 45.18268 45.03982
# [4,] 17.51314 31.88500 37.96784 37.77527
And a simple test, if radius 0 is used, then M1 and M2 should be identical (they are).
Note: this generally performs just fine in base R, with no fancy use of apply
or its cousins. Since this is a really straight-forward heuristic, it could easily be implemented with Rcpp to be significantly faster.
@AshokKrishnamurthy, see the edit.
– r2evans
Mar 24 at 19:24
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55320963%2fis-there-an-r-function-to-get-the-weighted-sum-of-neighboring-values-of-a-matr%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
I think the following does the weighted sum that you want. I'll be finding the neighbours in a similar way @r2evans did.
wtd_nbrs_sum <- function(input_matrix,
radius,
weight_matrix)
temp_1 <- matrix(data = 0,
nrow = nrow(x = input_matrix),
ncol = radius)
temp_2 <- matrix(data = 0,
nrow = radius,
ncol = ((2 * radius) + ncol(x = input_matrix)))
input_matrix_modified <- rbind(temp_2,
cbind(temp_1, input_matrix, temp_1),
temp_2)
output_matrix <- matrix(nrow = nrow(x = input_matrix),
ncol = ncol(x = input_matrix))
for(i in seq_len(length.out = nrow(x = input_matrix)))
for(j in seq_len(length.out = nrow(x = input_matrix)))
row_min <- (radius + (i - radius))
row_max <- (radius + (i + radius))
column_min <- (radius + (j - radius))
column_max <- (radius + (j + radius))
neighbours <- input_matrix_modified[(row_min:row_max), (column_min:column_max)]
weighted_sum <- sum(neighbours * weight_matrix)
output_matrix[i, j] <- weighted_sum
return(output_matrix)
r <- 4
c <- 4
n <- r*c
M <- matrix(data = 1:n,
nrow = r,
ncol = c)
R <- 1
wts <- matrix(data = c(exp(x = -sqrt(x = 2)), exp(x = -1), exp(x = -sqrt(x = 2)), exp(x = -1), 1, exp(x = -1), exp(x = -sqrt(x = 2)), exp(x = -1), exp(x = -sqrt(x = 2))),
nrow = 3,
ncol = 3)
wtd_nbrs_sum(input_matrix = M,
radius = R,
weight_matrix = wts)
#> [,1] [,2] [,3] [,4]
#> [1,] 5.033856 13.80347 24.16296 23.89239
#> [2,] 8.596195 20.66391 34.43985 32.84175
#> [3,] 11.186067 24.10789 37.88383 35.43163
#> [4,] 9.748491 19.86486 30.22435 28.60703
Created on 2019-03-24 by the reprex package (v0.2.1)
Hope this helps.
Thank you @yarnabrina I am getting an errorError in neighbours * weight_matrix : non-conformable arrays
when I changeR = 2
. I see thewts
matrix is 3 x 3 forR = 1
but as R increaseswts
also increases in the weighted distance calculation. Any help is highly appreciated.
– Ashok Krishnamurthy
Mar 24 at 18:21
@AshokKrishnamurthy If radius is R, then you'll be need to update the weight matrix to a(2R+1)x(2R+1)
matrix. So, if you tryR=2
, get a5x5
matrixwts
and then runwtd_nbrs_sum(input_matrix = M, radius = R, weight_matrix = wts)
.
– yarnabrina
Mar 25 at 1:24
add a comment |
I think the following does the weighted sum that you want. I'll be finding the neighbours in a similar way @r2evans did.
wtd_nbrs_sum <- function(input_matrix,
radius,
weight_matrix)
temp_1 <- matrix(data = 0,
nrow = nrow(x = input_matrix),
ncol = radius)
temp_2 <- matrix(data = 0,
nrow = radius,
ncol = ((2 * radius) + ncol(x = input_matrix)))
input_matrix_modified <- rbind(temp_2,
cbind(temp_1, input_matrix, temp_1),
temp_2)
output_matrix <- matrix(nrow = nrow(x = input_matrix),
ncol = ncol(x = input_matrix))
for(i in seq_len(length.out = nrow(x = input_matrix)))
for(j in seq_len(length.out = nrow(x = input_matrix)))
row_min <- (radius + (i - radius))
row_max <- (radius + (i + radius))
column_min <- (radius + (j - radius))
column_max <- (radius + (j + radius))
neighbours <- input_matrix_modified[(row_min:row_max), (column_min:column_max)]
weighted_sum <- sum(neighbours * weight_matrix)
output_matrix[i, j] <- weighted_sum
return(output_matrix)
r <- 4
c <- 4
n <- r*c
M <- matrix(data = 1:n,
nrow = r,
ncol = c)
R <- 1
wts <- matrix(data = c(exp(x = -sqrt(x = 2)), exp(x = -1), exp(x = -sqrt(x = 2)), exp(x = -1), 1, exp(x = -1), exp(x = -sqrt(x = 2)), exp(x = -1), exp(x = -sqrt(x = 2))),
nrow = 3,
ncol = 3)
wtd_nbrs_sum(input_matrix = M,
radius = R,
weight_matrix = wts)
#> [,1] [,2] [,3] [,4]
#> [1,] 5.033856 13.80347 24.16296 23.89239
#> [2,] 8.596195 20.66391 34.43985 32.84175
#> [3,] 11.186067 24.10789 37.88383 35.43163
#> [4,] 9.748491 19.86486 30.22435 28.60703
Created on 2019-03-24 by the reprex package (v0.2.1)
Hope this helps.
Thank you @yarnabrina I am getting an errorError in neighbours * weight_matrix : non-conformable arrays
when I changeR = 2
. I see thewts
matrix is 3 x 3 forR = 1
but as R increaseswts
also increases in the weighted distance calculation. Any help is highly appreciated.
– Ashok Krishnamurthy
Mar 24 at 18:21
@AshokKrishnamurthy If radius is R, then you'll be need to update the weight matrix to a(2R+1)x(2R+1)
matrix. So, if you tryR=2
, get a5x5
matrixwts
and then runwtd_nbrs_sum(input_matrix = M, radius = R, weight_matrix = wts)
.
– yarnabrina
Mar 25 at 1:24
add a comment |
I think the following does the weighted sum that you want. I'll be finding the neighbours in a similar way @r2evans did.
wtd_nbrs_sum <- function(input_matrix,
radius,
weight_matrix)
temp_1 <- matrix(data = 0,
nrow = nrow(x = input_matrix),
ncol = radius)
temp_2 <- matrix(data = 0,
nrow = radius,
ncol = ((2 * radius) + ncol(x = input_matrix)))
input_matrix_modified <- rbind(temp_2,
cbind(temp_1, input_matrix, temp_1),
temp_2)
output_matrix <- matrix(nrow = nrow(x = input_matrix),
ncol = ncol(x = input_matrix))
for(i in seq_len(length.out = nrow(x = input_matrix)))
for(j in seq_len(length.out = nrow(x = input_matrix)))
row_min <- (radius + (i - radius))
row_max <- (radius + (i + radius))
column_min <- (radius + (j - radius))
column_max <- (radius + (j + radius))
neighbours <- input_matrix_modified[(row_min:row_max), (column_min:column_max)]
weighted_sum <- sum(neighbours * weight_matrix)
output_matrix[i, j] <- weighted_sum
return(output_matrix)
r <- 4
c <- 4
n <- r*c
M <- matrix(data = 1:n,
nrow = r,
ncol = c)
R <- 1
wts <- matrix(data = c(exp(x = -sqrt(x = 2)), exp(x = -1), exp(x = -sqrt(x = 2)), exp(x = -1), 1, exp(x = -1), exp(x = -sqrt(x = 2)), exp(x = -1), exp(x = -sqrt(x = 2))),
nrow = 3,
ncol = 3)
wtd_nbrs_sum(input_matrix = M,
radius = R,
weight_matrix = wts)
#> [,1] [,2] [,3] [,4]
#> [1,] 5.033856 13.80347 24.16296 23.89239
#> [2,] 8.596195 20.66391 34.43985 32.84175
#> [3,] 11.186067 24.10789 37.88383 35.43163
#> [4,] 9.748491 19.86486 30.22435 28.60703
Created on 2019-03-24 by the reprex package (v0.2.1)
Hope this helps.
I think the following does the weighted sum that you want. I'll be finding the neighbours in a similar way @r2evans did.
wtd_nbrs_sum <- function(input_matrix,
radius,
weight_matrix)
temp_1 <- matrix(data = 0,
nrow = nrow(x = input_matrix),
ncol = radius)
temp_2 <- matrix(data = 0,
nrow = radius,
ncol = ((2 * radius) + ncol(x = input_matrix)))
input_matrix_modified <- rbind(temp_2,
cbind(temp_1, input_matrix, temp_1),
temp_2)
output_matrix <- matrix(nrow = nrow(x = input_matrix),
ncol = ncol(x = input_matrix))
for(i in seq_len(length.out = nrow(x = input_matrix)))
for(j in seq_len(length.out = nrow(x = input_matrix)))
row_min <- (radius + (i - radius))
row_max <- (radius + (i + radius))
column_min <- (radius + (j - radius))
column_max <- (radius + (j + radius))
neighbours <- input_matrix_modified[(row_min:row_max), (column_min:column_max)]
weighted_sum <- sum(neighbours * weight_matrix)
output_matrix[i, j] <- weighted_sum
return(output_matrix)
r <- 4
c <- 4
n <- r*c
M <- matrix(data = 1:n,
nrow = r,
ncol = c)
R <- 1
wts <- matrix(data = c(exp(x = -sqrt(x = 2)), exp(x = -1), exp(x = -sqrt(x = 2)), exp(x = -1), 1, exp(x = -1), exp(x = -sqrt(x = 2)), exp(x = -1), exp(x = -sqrt(x = 2))),
nrow = 3,
ncol = 3)
wtd_nbrs_sum(input_matrix = M,
radius = R,
weight_matrix = wts)
#> [,1] [,2] [,3] [,4]
#> [1,] 5.033856 13.80347 24.16296 23.89239
#> [2,] 8.596195 20.66391 34.43985 32.84175
#> [3,] 11.186067 24.10789 37.88383 35.43163
#> [4,] 9.748491 19.86486 30.22435 28.60703
Created on 2019-03-24 by the reprex package (v0.2.1)
Hope this helps.
answered Mar 24 at 15:48
yarnabrinayarnabrina
640111
640111
Thank you @yarnabrina I am getting an errorError in neighbours * weight_matrix : non-conformable arrays
when I changeR = 2
. I see thewts
matrix is 3 x 3 forR = 1
but as R increaseswts
also increases in the weighted distance calculation. Any help is highly appreciated.
– Ashok Krishnamurthy
Mar 24 at 18:21
@AshokKrishnamurthy If radius is R, then you'll be need to update the weight matrix to a(2R+1)x(2R+1)
matrix. So, if you tryR=2
, get a5x5
matrixwts
and then runwtd_nbrs_sum(input_matrix = M, radius = R, weight_matrix = wts)
.
– yarnabrina
Mar 25 at 1:24
add a comment |
Thank you @yarnabrina I am getting an errorError in neighbours * weight_matrix : non-conformable arrays
when I changeR = 2
. I see thewts
matrix is 3 x 3 forR = 1
but as R increaseswts
also increases in the weighted distance calculation. Any help is highly appreciated.
– Ashok Krishnamurthy
Mar 24 at 18:21
@AshokKrishnamurthy If radius is R, then you'll be need to update the weight matrix to a(2R+1)x(2R+1)
matrix. So, if you tryR=2
, get a5x5
matrixwts
and then runwtd_nbrs_sum(input_matrix = M, radius = R, weight_matrix = wts)
.
– yarnabrina
Mar 25 at 1:24
Thank you @yarnabrina I am getting an error
Error in neighbours * weight_matrix : non-conformable arrays
when I change R = 2
. I see the wts
matrix is 3 x 3 for R = 1
but as R increases wts
also increases in the weighted distance calculation. Any help is highly appreciated.– Ashok Krishnamurthy
Mar 24 at 18:21
Thank you @yarnabrina I am getting an error
Error in neighbours * weight_matrix : non-conformable arrays
when I change R = 2
. I see the wts
matrix is 3 x 3 for R = 1
but as R increases wts
also increases in the weighted distance calculation. Any help is highly appreciated.– Ashok Krishnamurthy
Mar 24 at 18:21
@AshokKrishnamurthy If radius is R, then you'll be need to update the weight matrix to a
(2R+1)x(2R+1)
matrix. So, if you try R=2
, get a 5x5
matrix wts
and then run wtd_nbrs_sum(input_matrix = M, radius = R, weight_matrix = wts)
.– yarnabrina
Mar 25 at 1:24
@AshokKrishnamurthy If radius is R, then you'll be need to update the weight matrix to a
(2R+1)x(2R+1)
matrix. So, if you try R=2
, get a 5x5
matrix wts
and then run wtd_nbrs_sum(input_matrix = M, radius = R, weight_matrix = wts)
.– yarnabrina
Mar 25 at 1:24
add a comment |
Edited to include weighted-sums.
There might be a really neat trick to doing it, but the most straight-forward (and maintainable) way is probably a simple two-for
-loop implementation.
M1 <- matrix(1:16, nr=4)
M1
# [,1] [,2] [,3] [,4]
# [1,] 1 5 9 13
# [2,] 2 6 10 14
# [3,] 3 7 11 15
# [4,] 4 8 12 16
The code:
get_neighbors <- function(M, radius = 1)
M2 <- M
M2[] <- 0
nr <- nrow(M)
nc <- ncol(M)
eg <- expand.grid((-radius):radius, (-radius):radius)
eg$wt <- exp(-sqrt(abs(eg[,1]) + abs(eg[,2])))
for (R in seq_len(nr))
for (C in seq_len(nc))
ind <- cbind(R + eg[,1], C + eg[,2], eg[,3])
ind <- ind[ 0 < ind[,1] & ind[,1] <= nr &
0 < ind[,2] & ind[,2] <= nc,, drop = FALSE ]
M2[R,C] <- sum(M[ind[,1:2, drop=FALSE]] * ind[,3])
M2
get_neighbors(M1, 1)
# [,1] [,2] [,3] [,4]
# [1,] 5.033856 13.80347 24.16296 23.89239
# [2,] 8.596195 20.66391 34.43985 32.84175
# [3,] 11.186067 24.10789 37.88383 35.43163
# [4,] 9.748491 19.86486 30.22435 28.60703
The same thing, with radius 2:
get_neighbors(M1, 2)
# [,1] [,2] [,3] [,4]
# [1,] 12.44761 25.64963 31.73247 32.70974
# [2,] 18.57765 35.96237 43.33862 43.51911
# [3,] 20.09836 37.80643 45.18268 45.03982
# [4,] 17.51314 31.88500 37.96784 37.77527
And a simple test, if radius 0 is used, then M1 and M2 should be identical (they are).
Note: this generally performs just fine in base R, with no fancy use of apply
or its cousins. Since this is a really straight-forward heuristic, it could easily be implemented with Rcpp to be significantly faster.
@AshokKrishnamurthy, see the edit.
– r2evans
Mar 24 at 19:24
add a comment |
Edited to include weighted-sums.
There might be a really neat trick to doing it, but the most straight-forward (and maintainable) way is probably a simple two-for
-loop implementation.
M1 <- matrix(1:16, nr=4)
M1
# [,1] [,2] [,3] [,4]
# [1,] 1 5 9 13
# [2,] 2 6 10 14
# [3,] 3 7 11 15
# [4,] 4 8 12 16
The code:
get_neighbors <- function(M, radius = 1)
M2 <- M
M2[] <- 0
nr <- nrow(M)
nc <- ncol(M)
eg <- expand.grid((-radius):radius, (-radius):radius)
eg$wt <- exp(-sqrt(abs(eg[,1]) + abs(eg[,2])))
for (R in seq_len(nr))
for (C in seq_len(nc))
ind <- cbind(R + eg[,1], C + eg[,2], eg[,3])
ind <- ind[ 0 < ind[,1] & ind[,1] <= nr &
0 < ind[,2] & ind[,2] <= nc,, drop = FALSE ]
M2[R,C] <- sum(M[ind[,1:2, drop=FALSE]] * ind[,3])
M2
get_neighbors(M1, 1)
# [,1] [,2] [,3] [,4]
# [1,] 5.033856 13.80347 24.16296 23.89239
# [2,] 8.596195 20.66391 34.43985 32.84175
# [3,] 11.186067 24.10789 37.88383 35.43163
# [4,] 9.748491 19.86486 30.22435 28.60703
The same thing, with radius 2:
get_neighbors(M1, 2)
# [,1] [,2] [,3] [,4]
# [1,] 12.44761 25.64963 31.73247 32.70974
# [2,] 18.57765 35.96237 43.33862 43.51911
# [3,] 20.09836 37.80643 45.18268 45.03982
# [4,] 17.51314 31.88500 37.96784 37.77527
And a simple test, if radius 0 is used, then M1 and M2 should be identical (they are).
Note: this generally performs just fine in base R, with no fancy use of apply
or its cousins. Since this is a really straight-forward heuristic, it could easily be implemented with Rcpp to be significantly faster.
@AshokKrishnamurthy, see the edit.
– r2evans
Mar 24 at 19:24
add a comment |
Edited to include weighted-sums.
There might be a really neat trick to doing it, but the most straight-forward (and maintainable) way is probably a simple two-for
-loop implementation.
M1 <- matrix(1:16, nr=4)
M1
# [,1] [,2] [,3] [,4]
# [1,] 1 5 9 13
# [2,] 2 6 10 14
# [3,] 3 7 11 15
# [4,] 4 8 12 16
The code:
get_neighbors <- function(M, radius = 1)
M2 <- M
M2[] <- 0
nr <- nrow(M)
nc <- ncol(M)
eg <- expand.grid((-radius):radius, (-radius):radius)
eg$wt <- exp(-sqrt(abs(eg[,1]) + abs(eg[,2])))
for (R in seq_len(nr))
for (C in seq_len(nc))
ind <- cbind(R + eg[,1], C + eg[,2], eg[,3])
ind <- ind[ 0 < ind[,1] & ind[,1] <= nr &
0 < ind[,2] & ind[,2] <= nc,, drop = FALSE ]
M2[R,C] <- sum(M[ind[,1:2, drop=FALSE]] * ind[,3])
M2
get_neighbors(M1, 1)
# [,1] [,2] [,3] [,4]
# [1,] 5.033856 13.80347 24.16296 23.89239
# [2,] 8.596195 20.66391 34.43985 32.84175
# [3,] 11.186067 24.10789 37.88383 35.43163
# [4,] 9.748491 19.86486 30.22435 28.60703
The same thing, with radius 2:
get_neighbors(M1, 2)
# [,1] [,2] [,3] [,4]
# [1,] 12.44761 25.64963 31.73247 32.70974
# [2,] 18.57765 35.96237 43.33862 43.51911
# [3,] 20.09836 37.80643 45.18268 45.03982
# [4,] 17.51314 31.88500 37.96784 37.77527
And a simple test, if radius 0 is used, then M1 and M2 should be identical (they are).
Note: this generally performs just fine in base R, with no fancy use of apply
or its cousins. Since this is a really straight-forward heuristic, it could easily be implemented with Rcpp to be significantly faster.
Edited to include weighted-sums.
There might be a really neat trick to doing it, but the most straight-forward (and maintainable) way is probably a simple two-for
-loop implementation.
M1 <- matrix(1:16, nr=4)
M1
# [,1] [,2] [,3] [,4]
# [1,] 1 5 9 13
# [2,] 2 6 10 14
# [3,] 3 7 11 15
# [4,] 4 8 12 16
The code:
get_neighbors <- function(M, radius = 1)
M2 <- M
M2[] <- 0
nr <- nrow(M)
nc <- ncol(M)
eg <- expand.grid((-radius):radius, (-radius):radius)
eg$wt <- exp(-sqrt(abs(eg[,1]) + abs(eg[,2])))
for (R in seq_len(nr))
for (C in seq_len(nc))
ind <- cbind(R + eg[,1], C + eg[,2], eg[,3])
ind <- ind[ 0 < ind[,1] & ind[,1] <= nr &
0 < ind[,2] & ind[,2] <= nc,, drop = FALSE ]
M2[R,C] <- sum(M[ind[,1:2, drop=FALSE]] * ind[,3])
M2
get_neighbors(M1, 1)
# [,1] [,2] [,3] [,4]
# [1,] 5.033856 13.80347 24.16296 23.89239
# [2,] 8.596195 20.66391 34.43985 32.84175
# [3,] 11.186067 24.10789 37.88383 35.43163
# [4,] 9.748491 19.86486 30.22435 28.60703
The same thing, with radius 2:
get_neighbors(M1, 2)
# [,1] [,2] [,3] [,4]
# [1,] 12.44761 25.64963 31.73247 32.70974
# [2,] 18.57765 35.96237 43.33862 43.51911
# [3,] 20.09836 37.80643 45.18268 45.03982
# [4,] 17.51314 31.88500 37.96784 37.77527
And a simple test, if radius 0 is used, then M1 and M2 should be identical (they are).
Note: this generally performs just fine in base R, with no fancy use of apply
or its cousins. Since this is a really straight-forward heuristic, it could easily be implemented with Rcpp to be significantly faster.
edited Mar 24 at 19:23
answered Mar 24 at 5:58
r2evansr2evans
29.4k33259
29.4k33259
@AshokKrishnamurthy, see the edit.
– r2evans
Mar 24 at 19:24
add a comment |
@AshokKrishnamurthy, see the edit.
– r2evans
Mar 24 at 19:24
@AshokKrishnamurthy, see the edit.
– r2evans
Mar 24 at 19:24
@AshokKrishnamurthy, see the edit.
– r2evans
Mar 24 at 19:24
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55320963%2fis-there-an-r-function-to-get-the-weighted-sum-of-neighboring-values-of-a-matr%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Please don't ever include
rm(list=ls())
in code posted in a question. It's akin to suggesting somebody run your code and it includes the oldformat C:
DOS command.– r2evans
Mar 24 at 5:50
1
Thank you r2evans. I ll remember to never include
rm(list=ls())
in the future.– Ashok Krishnamurthy
Mar 24 at 7:27