I have a shapefile (called "shp") containing 177 polygons i.e. 177 counties. This shapefile is overlaid on a raster. My raster (called "ras") is made of pixels having different pollution values.
Now I would like to extract all pixel values and their number of occurrences for each polygon.
This is exactly what the QGIS function "zonal histogram" is doing. But I would like to do the exact same thing in R.
I tried the extract() function and I managed to get a mean value per county, which is already a first step, but I would like to make a pixels distribution (histogram).
Sounds challenging. I'm not sure that I can help, but there may be people in the community that can, even though they don't have a magic snippet in their utils folder. But that's unlikely without a reprex, since few will try to reverse-engineer a problem.
Is there a way we can attach a csv document here ?
Or is it better to use the tibble function ?
Many thanks for your reply
Meanwhile I found a solution to my issue.
First I had to uninstall the "tidyr" package because there was a conflict with the extract() function.
It took me ages to figure this out.
Here is the final code:
# Libraries loading
library(raster)
library(rgdal)
library(sp)
# raster layer import
ras=raster("C:/*.tif")
# shapefile layer import
shp<-shapefile("C:/*.shp")
# Extract the values of the pixels raster per county
ext <- extract(ras, shp, method='simple')
# Function to tabulate pixel values by region & return a data frame
tabFunc <- function(indx, extracted, region, regname) {
dat <- as.data.frame(table(extracted[[indx]]))
dat$name <- region[[regname]][[indx]]
return(dat)
}
# run through each county & compute a table of the number
# of raster cells by pixel value. ("CODE" is the county code)
tabs <- lapply(seq(ext), tabFunc, ext, shp, "CODE")
# assemble into one data frame
df <- do.call(rbind, tabs)
# to see the data frame in R
print(df)
# table export
write.csv(df,"C:/*.csv", row.names = FALSE)
Glad you fixed it. Please mark the solution for the benefit of those to follow. No false modesty allowed.
For the data part of it: Only enough data to reproduce the issue is needed. It doesn't have to be your data, one of the built in datasets with comparable structure will do. It doesn't have to be all of the data, just enough to show the same behavior. And, as an added bonus.
dput(your_data
Will return a formal definition of the data object, which can be cut and pasted into the code reprex with
dput(your_data
followed by paste.
Here's a function with a slightly less verbose output:
require(clipr)
#> Loading required package: clipr
#> Welcome to clipr. See ?write_clip for advisories on writing to the clipboard in R.
require(magrittr)
#> Loading required package: magrittr
require(stringr)
#> Loading required package: stringr
specimen <- function(x)
deparse(x) %>%
str_c(collapse = '') %>%
str_replace_all('\\s+', ' ') %>%
str_replace_all('\\s*([^,\\()]+ =) (c\\()', '\n \\1\n \\2') %>%
str_replace_all('(,) (class =)', '\\1\n \\2') %>%
write_clip(allow_non_interactive = TRUE)
(Credit to the anonymous author from whom I ripped off at least the major pieces. Mea culpa.)