I'm currently working on visualizing the spatial density. However, I'm facing an issue where the density plot doesn't adequately represent areas with few sampled points, particularly in regions like Utah in this example where there are sparse data points.
sf_points <- data.frame(
lat = c(39.52, 39.62, 40.03, 40.00, 39.93, 39.94, 40.12, 40.54, 35.78, 35.77),
lon = c(-116.32, -116.00, -116.42, -116.40, -116.41, -116.41, -116.59, -116.56, -111.89, -111.51)
)
This is my method:
library(sf)
library(dplyr)
library(ggplot2)
library(spatstat)
sf_points<-dfst_as_sf%>%
(coords = c("lon", "lat"), crs = 4326) %>%
st_transform(32650)
ppp_points <- as.ppp(sf_points)
Window(ppp_points) <- as.owin(usa_map)
par(mar = rep(0, 4))
plot(ppp_points, main = "")
density_spatstat <- density(ppp_points, dimyx = 256)
density_stars <- stars::st_as_stars(density_spatstat)
density_sf <- st_as_sf(density_stars) %>%
st_set_crs(32650)
And then plotting
ggplot(usa_map) +
geom_sf(data = density_sf, aes(fill = v), col = NA) +
theme_bw() +
ggthemes::theme_map()+ geom_sf(data = st_boundary(usa_map))+
coord_sf(crs = st_crs("+proj=laea +lat_0=45 +lon_0=-100 +x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs"), datum = NA)+scale_fill_viridis_c(option = "c")
Despite using the scale_fill_viridis_c
function to adjust the color scheme, the density plot doesn't provide sufficient visual contrast to distinguish areas with varying densities of sampled points. I would like to enhance the visualization so that even regions with few sampled points are clearly discernible.
I'm seeking advice on how to adjust the color scheme or apply alternative visualization techniques that can better highlight variations in density, particularly in regions with sparse data points like Utah.
Any suggestions or guidance would be greatly appreciated. Thank you!
I can't reproduce your example (usa_map
is not found, and there's a syntax error somewhere in the code)
You don't say exactly what is wrong with the graphics output (other than that it "does not provide sufficient contrast").
The input parameter which has the biggest effect on the result is the smoothing bandwidth sigma
. This should be specified in the call to density()
. Your code does not specify sigma
so the code uses the default value of sigma
which may not be appropriate in this case. The call is dispatched to the method density.ppp
in the spatstat.explore
package. I suggest you read the help file for density.ppp
for guidance.
With very sparse data it is possible that the algorithm produces some pixel values which are negative (but extremely small) due to numerical artifacts. This could affect the graphics display if the graphics code is expecting nonnegative pixel values: it may render negative values as blanks. You can check whether any small negative values were in fact returned by typing range(density_spatstat)
or summary(density_spatstat)
or any(density_spatstat < 0)
. You can set positive=TRUE
in the call to density
to remove such values. See the help file for density.ppp
.
There are also numerous alternatives to density.ppp
which use adaptive smoothing, which may be more appropriate for your data. Again, see the help file for cross-references.