1

I have a raster made of values 1, 2, and NA. I am wanting to use the focal function with a 3x3 window to reassign cells with a new value. The attached image shows an example of the dataset and 3x3 window. I want the new assigned value to be the count of neighboring cells in the window that do not equal the center cell, excluding NA values. So, essentially, if the center cell = 1, I want it to count how many neighboring cells = 2, and vice versa. In this attached photo, the value would be 4, as the center value = 1, and there are four neighboring cells = 2.

example

I am using the code below, which works with the basic functions (mean, min, max, etc.) but does not have any function to do what I am looking for, as far as I can find.

focal.statistic <- focal(raster, window=window, function=function)

I need to create a new function doing what I described above, that can then be called with "function=" code. I have been thinking about if, then statements but am struggling to write this function...

This is similar to this post from many years ago, but I still cannot figure it out.

Jan
  • 2,245
  • 1
  • 2
  • 16
Hannah P
  • 13
  • 2

1 Answers1

1

Here is a possible function for counting the neighbour cells of the window which are not equal to the center (details below).

f = function (x) sum(x != x[5L] & x != -999, na.rm = TRUE)

Example as provided by you:

library(raster)

x <- matrix(c(
    c(1, 1, NA, NA, 1, 2),
    c(2, 2, 2, 1, 1, NA),
    c(2, 2, 1, 1, 2, NA),
    c(NA, NA, 2, 1, 2, NA),
    c(NA, NA, 2, 2, 2, NA),
    c(NA, NA, 1, 1, 2, NA)
),
nrow = 6)

r <- raster(x)

res <- as.matrix(focal(
    x = r,
    w = matrix(1, 3, 3),
    fun = f,
    pad = T,
    padValue = -999
))

> x
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    2    2   NA   NA   NA
[2,]    1    2    2   NA   NA   NA
[3,]   NA    2    1    2    2    1
[4,]   NA    1    1    1    2    1
[5,]    1    1    2    2    2    2
[6,]    2   NA   NA   NA   NA   NA

> res
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    2    2    0    0    0    0
[2,]    3    3    1    0    0    0
[3,]    0    4    4    3    3    2
[4,]    0    2    4    6    3    4
[5,]    1    2    4    2    2    1
[6,]    2    0    0    0    0    0

Explanation:

  • We call focal with a dummy padValue = -999. I use the pad value in order to take the edges of the matrix correctly into account.
  • In f() we take the sum a logical vector whose elements say whether the respective value is not equal to the center and not equal to the dummy value. Note that we refer to the center of the window matrix by x[5], if you take another window size, you have to adjust this (e.g. by x[13] for 5x5 windows).
Jan
  • 2,245
  • 1
  • 2
  • 16
  • `unlist(as.list(x))` doesn’t make sense. If you want to flatten a matrix, use `as.vector`. But you do not need to flatten the matrix here. Just `x != x[5]` works. — Furthermore, [you don’t need `return(y)`](https://stackoverflow.com/a/59090751/1968), and consequently you also don’t need the assignment. — Lastly, using `T` instead of `TRUE` is strongly discouraged since the former is a redefinable variable, but the latter is a fixed constant. — Ultimately, the entire function can be written as `f = function (x) sum(x != x[5L] & x != -999, na.rm = TRUE)`. – Konrad Rudolph Jul 13 '23 at 07:56
  • Thanks for the feedback, I edited my answer. – Jan Jul 13 '23 at 08:03
  • This worked! Thank you!! – Hannah P Jul 14 '23 at 12:25