Penetapan nilai bersyarat ke sel raster yang berdekatan?

12

Saya memiliki raster nilai:

m <- matrix(c(2,4,5,5,2,8,7,3,1,6,
         5,7,5,7,1,6,7,2,6,3,
         4,7,3,4,5,3,7,9,3,8,
         9,3,6,8,3,4,7,3,7,8,
         3,3,7,7,5,3,2,8,9,8,
         7,6,2,6,5,2,2,7,7,7,
         4,7,2,5,7,7,7,3,3,5,
         7,6,7,5,9,6,5,2,3,2,
         4,9,2,5,5,8,3,3,1,2,
         5,2,6,5,1,5,3,7,7,2),nrow=10, ncol=10, byrow = T)
r <- raster(m)
extent(r) <- matrix(c(0, 0, 10, 10), nrow=2)
plot(r)
text(r)

Dari raster ini, bagaimana saya bisa menetapkan nilai (atau mengubah nilai) ke 8 sel yang berdekatan dari sel saat ini menurut ilustrasi ini? Saya menempatkan titik merah di dalam sel saat ini dari baris kode ini:

points(xFromCol(r, col=5), yFromRow(r, row=5),col="red",pch=16)

masukkan deskripsi gambar di sini

Di sini, hasil yang diharapkan adalah:

masukkan deskripsi gambar di sini

di mana nilai sel saat ini (yaitu, 5 dalam nilai raster) diganti dengan 0.

Secara keseluruhan, nilai baru untuk 8 sel yang berdekatan harus dihitung sebagai berikut:

Nilai baru = rata-rata nilai sel yang terkandung dalam persegi panjang merah * jarak antara sel saat ini (titik merah) dan sel yang berdekatan (yaitu, sqrt (2) untuk sel yang berdekatan secara diagonal atau 1 sebaliknya)

Memperbarui

Ketika batas untuk sel yang berdekatan berada di luar batas raster, saya perlu menghitung nilai baru untuk sel yang berdekatan yang menghormati kondisi. Sel-sel yang berdekatan yang tidak menghormati kondisinya akan sama dengan "NA".

Misalnya, jika posisi referensi adalah c (1,1) alih-alih c (5,5) dengan menggunakan notasi [baris, kolom], hanya nilai baru di sudut kanan bawah yang dapat dihitung. Dengan demikian, hasil yang diharapkan adalah:

     [,1] [,2] [,3]       
[1,] NA   NA   NA         
[2,] NA   0    NA         
[3,] NA   NA   New_value

Misalnya, jika posisi referensi adalah c (3,1), hanya nilai-nilai baru di sudut kanan atas, kanan dan kanan bawah dapat dihitung. Dengan demikian, hasil yang diharapkan adalah:

     [,1] [,2] [,3]       
[1,] NA   NA   New_value         
[2,] NA   0    New_value         
[3,] NA   NA   New_value

Ini adalah upaya pertama saya untuk ini dengan menggunakan fungsi focaltetapi saya memiliki beberapa kesulitan untuk membuat kode otomatis.

Pilih sel yang berdekatan

mat_perc <- matrix(c(1,1,1,1,1,
                     1,1,1,1,1,
                     1,1,0,1,1,
                     1,1,1,1,1,
                     1,1,1,1,1), nrow=5, ncol=5, byrow = T)
cell_perc <- adjacent(r, cellFromRowCol(r, 5, 5), directions=mat_perc, pairs=FALSE, sorted=TRUE, include=TRUE)
r_perc <- rasterFromCells(r, cell_perc)
r_perc <- setValues(r_perc,extract(r, cell_perc))
plot(r_perc)
text(r_perc)

jika sel yang berdekatan terletak di sudut kiri atas sel saat ini

focal_m <- matrix(c(1,1,NA,1,1,NA,NA,NA,NA), nrow=3, ncol=3, byrow = T)
focal_function <- function(x) mean(x,na.rm=T)*sqrt(2)
test <- as.matrix(focal(r_perc, focal_m, focal_function))

jika sel yang berdekatan terletak di sudut tengah atas sel saat ini

focal_m <- matrix(c(1,1,1,1,1,1,NA,NA,NA), nrow=3, ncol=3, byrow = T)
focal_function <- function(x) mean(x,na.rm=T)
test <- as.matrix(focal(r_perc, focal_m, focal_function))

jika sel yang berdekatan terletak di sudut kiri atas sel saat ini

focal_m <- matrix(c(NA,1,1,NA,1,1,NA,NA,NA), nrow=3, ncol=3, byrow = T)
focal_function <- function(x) mean(x,na.rm=T)*sqrt(2)
test <- as.matrix(focal(r_perc, focal_m, focal_function))

jika sel yang berdekatan terletak di sudut kiri sel saat ini

focal_m <- matrix(c(1,1,NA,1,1,NA,1,1,NA), nrow=3, ncol=3, byrow = T)
focal_function <- function(x) mean(x,na.rm=T)
test <- as.matrix(focal(r_perc, focal_m, focal_function))

jika sel yang berdekatan terletak di sudut kanan sel saat ini

focal_m <- matrix(c(NA,1,1,NA,1,1,NA,1,1), nrow=3, ncol=3, byrow = T)
focal_function <- function(x) mean(x,na.rm=T)
test <- as.matrix(focal(r_perc, focal_m, focal_function))

jika sel yang berdekatan terletak di sudut kiri bawah sel saat ini

focal_m <- matrix(c(NA,NA,NA,1,1,NA,1,1,NA), nrow=3, ncol=3, byrow = T)
focal_function <- function(x) mean(x,na.rm=T)*sqrt(2)
test <- as.matrix(focal(r_perc, focal_m, focal_function))

jika sel yang berdekatan terletak di sudut tengah-bawah sel saat ini

focal_m <- matrix(c(NA,NA,NA,1,1,1,1,1,1), nrow=3, ncol=3, byrow = T)
focal_function <- function(x) mean(x,na.rm=T)
test <- as.matrix(focal(r_perc, focal_m, focal_function))

jika sel yang berdekatan terletak di sudut kanan bawah sel saat ini

focal_m <- matrix(c(NA,NA,NA,NA,1,1,NA,1,1), nrow=3, ncol=3, byrow = T)
focal_function <- function(x) mean(x,na.rm=T)*sqrt(2)
test <- as.matrix(focal(r_perc, focal_m, focal_function))
Pierre
sumber
+1 Saya berharap semua pertanyaan dijebak dengan baik! Apakah Anda mencari operasi fokus (statistik jendela bergerak)? Lihat rasterpaket R dan focal()fungsinya (hlm. 90 dokumentasi): cran.r-project.org/web/packages/raster/raster.pdf
Aaron
Terima kasih banyak Aaron untuk saran Anda! Memang, fungsi fokus sepertinya sangat berguna tetapi saya tidak terbiasa dengannya. Misalnya, untuk sel yang berdekatan = 8 (gambar di sudut kiri atas), saya menguji mat <- matrix(c(1,1,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0), nrow=5, ncol=5, byrow = T) f.rast <- function(x) mean(x)*sqrt(2) aggr <- as.matrix(focal(r, mat, f.rast)). Bagaimana saya bisa mendapatkan hasil hanya untuk 8 sel yang berdekatan dari sel saat ini dan tidak semua raster? Di sini, hasilnya harus: res <- matrix(c(7.42,0,0,0,0,0,0,0,0), nrow=3, ncol=3, byrow = T). Terima kasih banyak !
Pierre
@ Pierre Apakah Anda perlu menghitung nilai yang berdekatan hanya untuk posisi baris 5, col 5? Atau pindahkan posisi referensi ini misalnya ke baris posisi referensi baru 6, col 6?
Guzmán
2
Bisakah Anda menjelaskan lebih lanjut (mengedit pertanyaan Anda) tentang bagaimana Anda perlu menghitung nilai yang berdekatan ketika batas untuk sel yang berdekatan berada di luar batas raster? Misalnya: baris 1, kolom 1.
Guzmán
1
Anda contoh tidak masuk akal. Pada yang pertama, jika posisi referensi adalah c (1,1), maka hanya kanan bawah c (2,2) yang akan mendapatkan nilai baru tetapi Anda telah menunjukkan bahwa c (3,3) mendapatkan New_Value. Selain itu c (1,1) akan menjadi 0 bukan c (2,2).
Farid Cheraghi

Jawaban:

4

Fungsi di AssignValuesToAdjacentRasterCellsbawah ini mengembalikan objek RasterLayer baru dengan nilai yang diinginkan ditetapkan dari input raster asli . Fungsi memeriksa apakah sel yang berdekatan dari posisi referensi berada di dalam batas raster. Ini juga menampilkan pesan jika ada yang keluar. Jika Anda perlu memindahkan posisi referensi, Anda cukup menulis iterasi mengubah posisi input ke c ( i , j ).

Input data

# Load packages
library("raster")

# Load matrix data
m <- matrix(c(2,4,5,5,2,8,7,3,1,6,
              5,7,5,7,1,6,7,2,6,3,
              4,7,3,4,5,3,7,9,3,8,
              9,3,6,8,3,4,7,3,7,8,
              3,3,7,7,5,3,2,8,9,8,
              7,6,2,6,5,2,2,7,7,7,
              4,7,2,5,7,7,7,3,3,5,
              7,6,7,5,9,6,5,2,3,2,
              4,9,2,5,5,8,3,3,1,2,
              5,2,6,5,1,5,3,7,7,2), nrow=10, ncol=10, byrow = TRUE)

# Convert matrix to RasterLayer object
r <- raster(m)

# Assign extent to raster
extent(r) <- matrix(c(0, 0, 10, 10), nrow=2)

# Plot original raster
plot(r)
text(r)
points(xFromCol(r, col=5), yFromRow(r, row=5), col="red", pch=16)

Fungsi

# Function to assigning values to the adjacent raster cells based on conditions
# Input raster: RasterLayer object
# Input position: two-dimension vector (e.g. c(5,5))

AssignValuesToAdjacentRasterCells <- function(raster, position) {

  # Reference position
  rowPosition = position[1]
  colPosition = position[2]

  # Adjacent cells positions
  adjacentBelow1 = rowPosition + 1
  adjacentBelow2 = rowPosition + 2
  adjacentUpper1 = rowPosition - 1
  adjacentUpper2 = rowPosition - 2
  adjacentLeft1 = colPosition - 1 
  adjacentLeft2 = colPosition - 2 
  adjacentRight1 = colPosition + 1
  adjacentRight2 = colPosition + 2

  # Check if adjacent cells positions are out of raster positions limits
  belowBound1 = adjacentBelow1 <= nrow(raster)
  belowBound2 = adjacentBelow2 <= nrow(raster)
  upperBound1 = adjacentUpper1 > 0
  upperBound2 = adjacentUpper2 > 0
  leftBound1 = adjacentLeft1 > 0 
  leftBound2 = adjacentLeft2 > 0 
  rightBound1 = adjacentRight1 <= ncol(raster)
  rightBound2 = adjacentRight2 <= ncol(raster) 

  if(upperBound2 & leftBound2) {

    val1 = mean(r[adjacentUpper2:adjacentUpper1, adjacentLeft2:adjacentLeft1]) * sqrt(2)

  } else {

    val1 = NA

  }

  if(upperBound2 & leftBound1 & rightBound1) {

    val2 = mean(r[adjacentUpper1:adjacentUpper2, adjacentLeft1:adjacentRight1])

  } else {

    val2 = NA

  }

  if(upperBound2 & rightBound2) {

    val3 = mean(r[adjacentUpper2:adjacentUpper1, adjacentRight1:adjacentRight2]) * sqrt(2)

  } else {

    val3 = NA

  }

  if(upperBound1 & belowBound1 & leftBound2) {

    val4 = mean(r[adjacentUpper1:adjacentBelow1, adjacentLeft2:adjacentLeft1])

  } else {

    val4 = NA

  }

  val5 = 0

  if(upperBound1 & belowBound1 & rightBound2) {

    val6 = mean(r[adjacentUpper1:adjacentBelow1, adjacentRight1:adjacentRight2])

  } else {

    val6 = NA

  }

  if(belowBound2 & leftBound2) {

    val7 = mean(r[adjacentBelow1:adjacentBelow2, adjacentLeft2:adjacentLeft1]) * sqrt(2)

  } else {

    val7 = NA

  }

  if(belowBound2 & leftBound1 & rightBound1) {

    val8 = mean(r[adjacentBelow1:adjacentBelow2, adjacentLeft1:adjacentRight1])

  } else {

    val8 = NA

  }

  if(belowBound2 & rightBound2) {

    val9 = mean(r[adjacentBelow1:adjacentBelow2, adjacentRight1:adjacentRight2]) * sqrt(2)

  } else {

    val9 = NA

  }

  # Build matrix
  mValues = matrix(data = c(val1, val2, val3,
                            val4, val5, val6,
                            val7, val8, val9), nrow = 3, ncol = 3, byrow = TRUE)    

  if(upperBound1) {

    a = adjacentUpper1

  } else {

    # Warning message
    cat(paste("\n Upper bound out of raster limits!"))
    a = rowPosition
    mValues <- mValues[-1,]

  }

  if(belowBound1) {

    b = adjacentBelow1

  } else {

    # Warning message
    cat(paste("\n Below bound out of raster limits!"))
    b = rowPosition
    mValues <- mValues[-3,]

  }

  if(leftBound1) {

    c = adjacentLeft1

  } else {

    # Warning message
    cat(paste("\n Left bound out of raster limits!"))
    c = colPosition
    mValues <- mValues[,-1]

  }

  if(rightBound1) {

    d = adjacentRight1

  } else {

    # Warning
    cat(paste("\n Right bound out of raster limits!"))
    d = colPosition
    mValues <- mValues[,-3]

  }

  # Convert matrix to RasterLayer object
  rValues = raster(mValues)

  # Assign values to raster
  raster[a:b, c:d] = rValues[,]  

  # Assign extent to raster
  extent(raster) <- matrix(c(0, 0, 10, 10), nrow = 2)

  # Return raster with assigned values
  return(raster)      

}

Jalankan contoh

# Run function AssignValuesToAdjacentRasterCells

# reference position (1,1)
example1 <- AssignValuesToAdjacentRasterCells(raster = r, position = c(1,1))

# reference position (1,5)
example2 <- AssignValuesToAdjacentRasterCells(raster = r, position = c(1,5))

# reference position (1,10)
example3 <- AssignValuesToAdjacentRasterCells(raster = r, position = c(1,10))

# reference position (5,1)
example4 <- AssignValuesToAdjacentRasterCells(raster = r, position = c(5,1))

# reference position (5,5)
example5 <- AssignValuesToAdjacentRasterCells(raster = r, position = c(5,5))

# reference position (5,10)
example6 <- AssignValuesToAdjacentRasterCells(raster = r, position = c(5,10))

# reference position (10,1)
example7 <- AssignValuesToAdjacentRasterCells(raster = r, position = c(10,1))

# reference position (10,5)
example8 <- AssignValuesToAdjacentRasterCells(raster = r, position = c(10,5))

# reference position (10,10)
example9 <- AssignValuesToAdjacentRasterCells(raster = r, position = c(10,10))

Plot contoh

# Plot examples
par(mfrow=(c(3,3)))

plot(example1, main = "Position ref. (1,1)")
text(example1)
points(xFromCol(example1, col=1), yFromRow(example1, row=1), col="red", cex=2.5, lwd=2.5)

plot(example2, main = "Position ref. (1,5)")
text(example2)
points(xFromCol(example2, col=5), yFromRow(example2, row=1), col="red", cex=2.5, lwd=2.5)

plot(example3, main = "Position ref. (1,10)")
text(example3)
points(xFromCol(example3, col=10), yFromRow(example3, row=1), col="red", cex=2.5, lwd=2.5)

plot(example4, main = "Position ref. (5,1)")
text(example4)
points(xFromCol(example4, col=1), yFromRow(example4, row=5), col="red", cex=2.5, lwd=2.5)

plot(example5, main = "Position ref. (5,5)")
text(example5)
points(xFromCol(example5, col=5), yFromRow(example5, row=5), col="red", cex=2.5, lwd=2.5)

plot(example6, main = "Position ref. (5,10)")
text(example6)
points(xFromCol(example6, col=10), yFromRow(example6, row=5), col="red", cex=2.5, lwd=2.5)

plot(example7, main = "Position ref. (10,1)")
text(example7)
points(xFromCol(example7, col=1), yFromRow(example7, row=10), col="red", cex=2.5, lwd=2.5)

plot(example8, main = "Position ref. (10,5)")
text(example8)
points(xFromCol(example8, col=5), yFromRow(example8, row=10), col="red", cex=2.5, lwd=2.5)

plot(example9, main = "Position ref. (10,10)")
text(example9)
points(xFromCol(example9, col=10), yFromRow(example9, row=10), col="red", cex=2.5, lwd=2.5)

Contoh gambar

exampleFigure

Catatan:NA nilai rata-rata sel putih

Guzmán
sumber
3

Untuk operator matriks pada matriks kecil ini masuk akal dan dapat ditelusuri. Namun, Anda mungkin ingin benar-benar memikirkan kembali logika Anda ketika menerapkan fungsi seperti ini ke raster besar. Secara konseptual, ini tidak benar-benar melacak dalam aplikasi umum. Anda berbicara tentang apa yang secara tradisional disebut sebagai statistik blok. Namun, statistik blok pada dasarnya dimulai pada satu sudut raster dan mengganti blok nilai, dalam ukuran jendela yang ditentukan, dengan operator. Biasanya jenis operator ini adalah untuk mengumpulkan data. Akan jauh lebih mudah ditelusuri jika Anda berpikir dalam hal menggunakan kondisi untuk menghitung nilai tengah dari sebuah matriks. Dengan cara ini Anda dapat dengan mudah menggunakan fungsi fokus.

Hanya perlu diingat bahwa fungsi fokus raster membaca dalam blok data yang mewakili nilai-nilai fokus dalam lingkungan yang ditentukan berdasarkan matriks yang diteruskan ke argumen w. Hasilnya adalah vektor untuk masing-masing lingkungan dan hasil dari operator fokus ditugaskan hanya untuk sel fokus dan bukan seluruh lingkungan. Anggap saja mengambil matriks yang mengelilingi nilai sel, beroperasi di atasnya, menetapkan nilai baru ke sel lalu pindah ke sel berikutnya.

Jika Anda memastikan bahwa na.rm = FALSE maka vektor akan selalu mewakili lingkungan yang tepat (mis., Vektor dengan panjang yang sama) dan dipaksa menjadi objek matriks yang dapat dioperasikan di dalam suatu fungsi. Karena itu, Anda cukup menulis fungsi yang mengambil vektor harapan, memaksa ke dalam matriks, menerapkan logika notasi lingkungan Anda dan kemudian menetapkan nilai tunggal sebagai hasilnya. Fungsi ini kemudian dapat diteruskan ke fungsi raster :: focal.

Inilah yang akan terjadi pada setiap sel berdasarkan pada paksaan sederhana dan evaluasi jendela fokus. Objek "w" pada dasarnya akan menjadi definisi matriks yang sama bahwa seseorang akan melewati argumen w dalam focal. Inilah yang mendefinisikan ukuran vektor subset di setiap evaluasi fokus.

w=c(5,5)
x <- runif(w[1]*w[2])
x[25] <- NA
print(x)
( x <- matrix(x, nrow=w[1], ncol=w[2]) ) 
( se <- mean(x, na.rm=TRUE) * sqrt(2) )
ifelse( as.vector(x[(length(as.vector(x)) + 1)/2]) <= se, 1, 0) 

Sekarang buat fungsi yang bisa diterapkan untuk fokus menerapkan logika di atas. Dalam hal ini Anda bisa menetapkan objek se sebagai nilai atau menggunakannya sebagai kondisi dalam sesuatu seperti "ifelse" untuk menetapkan nilai berdasarkan evaluasi. Saya menambahkan pernyataan ifelse untuk menggambarkan bagaimana seseorang akan mengevaluasi beberapa kondisi lingkungan dan menerapkan kondisi posisi matriks (notasi lingkungan). Dalam fungsi dummy ini, paksaan x ke matriks sama sekali tidak perlu dan hanya untuk menggambarkan bagaimana hal itu akan dilakukan. Satu dapat menerapkan kondisi notasi lingkungan langsung ke vektor, tanpa paksaan matriks, karena posisi dalam vektor akan berlaku untuk lokasinya di jendela fokus dan tetap tetap.

f.rast <- function(x, dims=c(5,5)) {
  x <- matrix(x, nrow=dims[1], ncol=dims[2]) 
  se <- mean(x, na.rm=TRUE) * sqrt(2)
  ifelse( as.vector(x[(length(as.vector(x)) + 1)/2]) <= se, 1, 0)   
}  

Dan menerapkannya pada raster

library(raster)
r <- raster(nrows=100, ncols=100)
  r[] <- runif( ncell(r) )
  plot(r)

( r.class <- focal(r, w = matrix(1, nrow=w[1], ncol=w[2]), fun=f.rast) )
plot(r.class)  
Jeffrey Evans
sumber
2

Anda dapat dengan mudah memperbarui nilai raster dengan menyetel raster menggunakan notasi [row, col]. Perhatikan saja bahwa baris dan kolom dimulai dari sudut kiri atas raster; r [1,1] adalah indeks piksel kiri atas dan r [2,1] adalah yang di bawah r [1,1].

masukkan deskripsi gambar di sini

# the function to update raster cell values
focal_raster_update <- function(r, row, col) {
  # copy the raster to hold the temporary values
  r_copy <- r
  r_copy[row,col] <- 0
  #upper left
  r_copy[row-1,col-1] <- mean(r[(row-2):(row-1),(col-2):(col-1)]) * sqrt(2)
  #upper mid
  r_copy[row-1,col] <- mean(r[(row-2):(row-1),(col-1):(col+1)])
  #upper right
  r_copy[row-1,col+1] <- mean(r[(row-2):(row-1),(col+1):(col+2)]) * sqrt(2)
  #left
  r_copy[row,col-1] <- mean(r[(row-1):(row+1),(col-2):(col-1)])
  #right
  r_copy[row,col+1] <- mean(r[(row-1):(row+1),(col+1):(col+2)])
  #bottom left
  r_copy[row+1,col-1] <- mean(r[(row+1):(row+2),(col-2):(col-1)]) * sqrt(2)
  #bottom mid
  r_copy[row+1,col] <- mean(r[(row+1):(row+2),(col-1):(col+1)])
  #bottom right
  r_copy[row+1,col+1] <- mean(r[(row+1):(row+2),(col+1):(col+2)]) * sqrt(2)
  return(r_copy)
}
col <- 5
row <- 5
r <- focal_raster_update(r,row,col)

dev.set(1)
plot(r)
text(r,digits=2)
Farid Cheraghi
sumber