Smoothing out ggplot2 map

前端 未结 2 1497
旧巷少年郎
旧巷少年郎 2020-12-08 11:34

Previous Posts

Cleaning up a map using geom_tile

Get boundaries to come through on states

Problem/Question

I\'m trying to smooth out some

相关标签:
2条回答
  • 2020-12-08 12:22

    The previous answer was prbly not optimal (or accurate) for your needs. This is a bit of a hack:

    gg <- ggplot() 
    gg <- gg + geom_polygon(data=subset(map_data("state"), region %in% regions), 
                            aes(x=long, y=lat, group=group))
    gg <- gg + geom_point(data=PRISM_1895_db, aes(x=longitude, y=latitude, color=APPT), 
                          size=5, alpha=1/15, shape=19)
    gg <- gg + scale_color_gradient(low="#023858", high="#ece7f2")
    gg <- gg + geom_polygon(data=subset(map_data("state"), region %in% regions), 
                            aes(x=long, y=lat, group=group), color="white", fill=NA)
    gg <- gg + coord_equal()
    gg
    

    that requires changing size in geom_point for larger plots, but you get a better gradient effect than the stat_summary2d behavior and it's conveying the same information.

    enter image description here

    Another option would be to interpolate more APPT values between the longitude & latitudes you have, then convert that to a more dense raster object and plot it with geom_raster like in the example you provided.

    0 讨论(0)
  • 2020-12-08 12:36

    The CRAN spatial view got me started on "Kriging". The code below takes ~7 minutes to run on my laptop. You could try simpler interpolations (e.g., some sort of spline). You might also remove some of the locations from the high-density regions. You don't need all of those spots to get the same heatmap. As far as I know, there is no easy way to create a true gradient with ggplot2 (gridSVG has a few options but nothing like the "grid gradient" you would find in a fancy SVG editor).

    enter image description here

    As requested, here is interpolation using splines (much faster). Alot of the code is taken from Plotting contours on an irregular grid.

    enter image description here

    Code for kriging:

    library(data.table)
    library(ggplot2)
    library(automap)
    
    # Data munging
    states=c("AR","IL","MO")
    regions=c("arkansas","illinois","missouri")
    PRISM_1895_db = as.data.frame(fread("./Downloads/PRISM_1895_db.csv"))
    sub_data = PRISM_1895_db[PRISM_1895_db$state %in% states,c("latitude","longitude","APPT")]
    coord_vars = c("latitude","longitude")
    data_vars = setdiff(colnames(sub_data), coord_vars)
    sp_points = SpatialPoints(sub_data[,coord_vars])
    sp_df = SpatialPointsDataFrame(sp_points, sub_data[,data_vars,drop=FALSE])
    
    # Create a fine grid
    pixels_per_side = 200
    bottom.left = apply(sp_points@coords,2,min)
    top.right = apply(sp_points@coords,2,max)
    margin = abs((top.right-bottom.left))/10
    bottom.left = bottom.left-margin
    top.right = top.right+margin
    pixel.size = abs(top.right-bottom.left)/pixels_per_side
    g = GridTopology(cellcentre.offset=bottom.left,
                 cellsize=pixel.size,
                 cells.dim=c(pixels_per_side,pixels_per_side))
    
    # Clip the grid to the state regions
    map_base_data = subset(map_data("state"), region %in% regions)
    colnames(map_base_data)[match(c("long","lat"),colnames(map_base_data))] = c("longitude","latitude")
    foo = function(x) {
      state = unique(x$region)
      print(state)
      Polygons(list(Polygon(x[,c("latitude","longitude")])),ID=state)
    }
    state_pg = SpatialPolygons(dlply(map_base_data, .(region), foo))
    grid_points = SpatialPoints(g)
    in_points = !is.na(over(grid_points,state_pg))
    fit_points = SpatialPoints(as.data.frame(grid_points)[in_points,])
    
    # Do kriging
    krig = autoKrige(APPT~1, sp_df, new_data=fit_points)
    interp_data = as.data.frame(krig$krige_output)
    colnames(interp_data) = c("latitude","longitude","APPT_pred","APPT_var","APPT_stdev")
    
    # Set up map plot
    map_base_aesthetics = aes(x=longitude, y=latitude, group=group)
    map_base = geom_polygon(data=map_base_data, map_base_aesthetics)
    borders = geom_polygon(data=map_base_data, map_base_aesthetics, color="black", fill=NA)
    
    nbin=20
    ggplot(data=interp_data, aes(x=longitude, y=latitude)) + 
      geom_tile(aes(fill=APPT_pred),color=NA) +
      stat_contour(aes(z=APPT_pred), bins=nbin, color="#999999") +
      scale_fill_gradient2(low="blue",mid="white",high="red", midpoint=mean(interp_data$APPT_pred)) +
      borders +
      coord_equal() +
      geom_point(data=sub_data,color="black",size=0.3)
    

    Code for spline interpolation:

    library(data.table)
    library(ggplot2)
    library(automap)
    library(plyr)
    library(akima)
    
    # Data munging
    sub_data = as.data.frame(fread("./Downloads/PRISM_1895_db_all.csv"))
    coord_vars = c("latitude","longitude")
    data_vars = setdiff(colnames(sub_data), coord_vars)
    sp_points = SpatialPoints(sub_data[,coord_vars])
    sp_df = SpatialPointsDataFrame(sp_points, sub_data[,data_vars,drop=FALSE])
    
    # Clip the grid to the state regions
    regions<- c("north dakota","south dakota","nebraska","kansas","oklahoma","texas",
                "minnesota","iowa","missouri","arkansas", "illinois", "indiana", "wisconsin")
    map_base_data = subset(map_data("state"), region %in% regions)
    colnames(map_base_data)[match(c("long","lat"),colnames(map_base_data))] = c("longitude","latitude")
    foo = function(x) {
      state = unique(x$region)
      print(state)
      Polygons(list(Polygon(x[,c("latitude","longitude")])),ID=state)
    }
    state_pg = SpatialPolygons(dlply(map_base_data, .(region), foo))
    
    # Set up map plot
    map_base_aesthetics = aes(x=longitude, y=latitude, group=group)
    map_base = geom_polygon(data=map_base_data, map_base_aesthetics)
    borders = geom_polygon(data=map_base_data, map_base_aesthetics, color="black", fill=NA)
    
    # Do spline interpolation with the akima package
    fld = with(sub_data, interp(x = longitude, y = latitude, z = APPT, duplicate="median",
                                xo=seq(min(map_base_data$longitude), max(map_base_data$longitude), length = 100),
                                yo=seq(min(map_base_data$latitude), max(map_base_data$latitude), length = 100),
                                extrap=TRUE, linear=FALSE))
    melt_x = rep(fld$x, times=length(fld$y))
    melt_y = rep(fld$y, each=length(fld$x))
    melt_z = as.vector(fld$z)
    level_data = data.frame(longitude=melt_x, latitude=melt_y, APPT=melt_z)
    interp_data = na.omit(level_data)
    grid_points = SpatialPoints(interp_data[,2:1])
    in_points = !is.na(over(grid_points,state_pg))
    inside_points = interp_data[in_points, ]
    
    ggplot(data=inside_points, aes(x=longitude, y=latitude)) + 
      geom_tile(aes(fill=APPT)) + 
      stat_contour(aes(z=APPT)) +
      coord_equal() + 
      scale_fill_gradient2(low="blue",mid="white",high="red", midpoint=mean(inside_points$APPT)) +
      borders
    
    0 讨论(0)
提交回复
热议问题