R Plot Filled Longitude-Latitude Grid Cells on Map - r

I have a data frame containing a number of (x,y,z) data points, (x,y) is the lower-right coordinate of a longitude-latitude cell of size w (e.g. a 1-degree grid). The z value has been averaged over this cell.
I'd like to plot these points in R so that the entire grid cell is filled with some colour derived from z.
The result would look something like one of these images:
The projection itself (e.g. Lambert conformal conic, equirectangular) isn't important, just the grid cell plotting.
My data is sparse: not every longitude-latitude cell will have data associated with it.
My hope would be a solution similar to
library(maps)
map("state")
grid_points(my_data,c("x","y","z"),0.5)
where 0.5 is the grid resolution above, indicating a 0.5-degree cell.
Any thoughts?
Thanks!

An alternative to using either spplot or image is to use ggplot2. The relevant geometries are geom_raster and geom_tile. The first is supposed to perform better and yield smaller files, and the second is more standard. The following example call:
ggplot(aes(x = x, y = y, fill = value), data = dat_grid) + geom_tile() +
geom_path(data = ant_ggplot)
orginates from this blogpost of mine. In addition, ggplot2 supports a range of projections through the mapproj package, see coord_map for more details.
The following is a working example (provided you've defined YOUR_DATA to have x,y,z columns):
library(ggplot2)
library(maps)
us_states <- map_data("state")
(ggplot(aes(x=x,y=y,fill=z),data=YOUR_DATA) + geom_tile())+geom_polygon(data=us_states,aes(x=long, y=lat, group=group), colour="black", fill="white", alpha=0)

If your data.frame is "x", try this:
library(sp)
coordinates(x) <- c("x", "y", "z")
gridded(x) <- TRUE
image(x, col = terrain.colors(256), useRaster = TRUE)
To get a really exact answer you should provide a sample of your data, hopefully an entire data.frame or the source where you download and the code you used to read it into R.
If the code above fails at the gridded()<- step then it's likely your x and y values don't actually provide a regular grid, which is implied by your plots. If they really are gridded longitude/latitude values and you need to project them to the ones in your image then see the raster package, or more generally the rgdal package.
library(raster)
?projectRaster
library(rgdal)
?project
?spTransform
(The plots look to me like one of the "Albers Equal Area and Lambert Conformal Conic Projections of North America" as shown on this site: http://www.colorado.edu/geography/gcraft/notes/mapproj/mapproj_f.html).
See http://spatialreference.org to get the PROJ.4 string for your projection which you can use in sp or raster.

I tried to do that kind of map recently and ended up using function interp of library akima to intrapolate my z data into a regular grid before plotting (any kind of projections will have to be done prior to the use of interp):
library(akima)
interp(x,y,z,xo=seq(min(x),max(x),by=0.5),yo=seq(min(y),max(y),by=0.5),extrap=FALSE,linear=TRUE) -> xygrid
image(xygrid,breaks=seq(min(z),max(z),length=10), col=1:10)

You can do this:
library(raster)
r <- rasterFromXYZ(xyz)
plot(r)

Related

How to plot colored circles knowing X/Y coordinates, radius and a continuous 3rd parameter in R

In a telecommunication project I have a data basis of a list of antennas with their XY coordinates, emission radius and frequencies. I would like to represent with circles the covered area of each antennas, with a specific color depending on the frequency.
Ive been looking for libraries, but I'm very new to R and programmation in general, and I don't find any easy and simple ones. What would you recommend ?
Thank you for any help
You can do it with ggplot2 and ggforce package, like this:
# First generate a sample data
data <- data.frame(x=rnorm(50),y=rnorm(50),radius = rnorm(50,sd=0.1),freq = factor(1:5,levels=1:5))
# Load the package
library(ggplot2)
library(ggforce)
# Plot
ggplot(data=data,aes(x0=x,y0=y,col=freq,r=radius)) + geom_circle() +
coord_fixed()

Plotting nb object in ggplot?

I would like to plot the outline of UK, along with an nb object that I generated from a spatial points dataframe.
The problem is that the outline of UK takes really, really long to plot --it keeps crashing my Rstudio. This for example, either take really long to load or my Rstudio just stops responding.
library(raster)
UK_gadm <- getData("GADM", country="GB", level=0)
plot(UK_gadm)
So I resorted to using ggplot2 from this solution where I can get the outline of UK like in a fraction of a second with the following commands:
library(ggplot2)
UK <- map_data(map = "world", region = "UK") # changed map to "world"
ggplot(data = UK, aes(x = long, y = lat, group = group)) +
geom_polygon() +
coord_map()
The issue now is that I would like the nb object to be plotting against the backdrop of the outline of UK -- however, this seems only achievable in base R like for example:
plot(orotl.shp, xlim=c(-125, -115), ylim=c(42,47))
plot(orstationc.neighbors.dist, orstationc.loc, add=T, lwd=2, col="blue")
Is there any way I could plot nb objects in ggplot or is there a way for R to plot the outline of UK without crashing my computer with the base R plot function?
Managed to find a fast, simple solution after a whole night of effort. Hope this helps someone else with a similar issue.
Just to elaborate on the goal: plot a neighbours object (nb) against a shapefile. This is to visualise the linkages among certain coordinates. After some googling, I think this can only be done with base R's plot function. The problem however, was loading a country's shapefile (downloaded from official sources/gadm)-- its too big.
To solve this issue, get a more generalised, simple map of the country via the maps package, turn it into a shapefile and then plot it alongside the neighbours object.
Here's the code:
library(spdep)
# get your neighbour object from your spatial points df
rest_neighbours <- dnearneigh(rest_spdf,0,1)
library(maps)
# get boundary of UK
UK_map <- sf::st_as_sf(maps::map(database='world',regions='UK', plot = FALSE, fill = TRUE))
# write to shapefile
st_write(UK_map, 'shapefiles/UK.shp')
# henceforth, we can just call the shapefile
UK <- readOGR('shapefiles/UK.shp')
# plot the boundary and the neighbours
plot(UK)
plot(rest_neighbours, rest_coords, add=T, lwd=2, col="blue")
I did not realise that official boundary files are often really detailed which also means that they are really huge and I'm glad that there's ready-made watered down versions of the maps available in the maps package of r. (Sorry if you already knew -- I'm still learning!)
Hope this helps anyone else!

3D interactive surface plot with spatial data

I would like to create an interactive 3D surface plot of depths in a lake, ideally using the plotly or rgl libraries. I have extracted my data from a SpatialLinesDataFrame of contour lines in Gauss-Krueger/EPSG:31468 CRS, i.e. metric units. Now each contour line produces a set of coordinates with the same depth value. The resulting data frame is rather large, but looks something like this:
set.seed(41)
xx <- rnorm(100,4448929,100)
yy <- rnorm(100,5308097,100)
zz <- c(rep(-10,10),rep(-20,10),rep(-30,10),rep(-40,10),rep(-50,10),rep(-60,10),rep(-70,10),rep(-80,10),rep(-90,10),rep(-100,10))
df <- data.frame(xx,yy,zz)
I have tried plotting the data with plotly as in this example and with rgl as in this post. In both cases I get error messages relating to my data not being in a matrix format, i.e. where x- and y-values are represented as row- and column-numbers.
What does work, is using the add_trace command in plotly:
plot_ly() %>% add_trace(df,x = ~df$xx, y = ~df$yy, z = ~df$zz,type="mesh3d")
However, the resulting graph not only lacks the fancy colour legend of the add_surface command, but more importantly, warps the x- and y-values in relation to the z-values. The z-values are shown much too large, although all have the same metric unit.
I have also tried reshaping the data frame to a matrix as in this post, but it either doesn't work at all, or gives me a matrix consisting almost entirely of NAs. I can only speculate that the number of coordinates that have depth values attached is very small in comparison to all x-y-combinations of coordinates in that range?
Any suggestions will be much appreciated - thanks!
Those are randomly located points, so rgl::persp3d can't handle them directly. However, you can follow the example in ?rgl::persp3d.deldir to triangulate them and then plot. For example,
dxyz <- deldir::deldir(df$xx, df$yy, z = df$zz, suppressMsgs=TRUE)
persp3d(dxyz, col = "lightblue")
This results in a pretty ugly picture, but with some work (e.g. fixing the axis labels, using real data) you should get something reasonable.

Plot a raster using hexes in ggplot2

I have a GIS raster data frame that I would like to plot using hexagonal tiles. The standard method using tile_geom() is straightforward:
ggplot(raster_df, aes(x, y, fill=blabla)) + geom_tile()
Howewer, I would really like my raster points to be displayed as hexes instead of rects for aesthetic reasons. The end result should be something like in this blog post: http://www.statsblogs.com/2014/09/02/how-to-create-a-hexagonal-bin-plot-in-sas/
I tried using geom_hex() instead of geom_tile(), but because geom_hex() seems to be intended with binning in mind, I can't figure out how to hack it to display my data instead. I would like for every raster point to correspond to a hex, i.e. have no binning at all!
Thank you for any suggestions.
Edit: as requested, here is a sample data raster (its actually very close to what I am using, as I want to plot a world map and colour each raster point according to a custom statistic)
library(maptools)
library(raster)
library(ggplot2)
data('wrld_simpl')
raster_df <- as.data.frame(rasterToPoints(rasterize(wrld_simpl, raster(res=5))))
raster_df$blabla <- rnorm(nrow(raster_df))
It looks as though this might be due to the implementation of geom_hex in ggplot2. I've used this package for a few years, and my first guess is to try:
ggplot(raster_df, aes(x, y, fill=blabla)) + geom_hex(stat="identity")
But this throws an error:
Error in ggplot2:::hexGrob(x = raster_df$x, y = raster_df$y, fill = raster_df$blabla) :
could not find function "hexcoords"
So I looked for the function hexcoords, which appears in the hexbin package. I explicity load that package and try again:
library(hexbin)
ggplot(raster_df, aes(x, y, fill=blabla)) + geom_hex(stat="identity")
And that works. The result isn't particularly beautiful, so it might be better to use the hexbin package a little more directly.
It doesn't seem that geom_hex() was designed to directly plot the data to hexagons without the interim step of stat = "binhex", which is different from many of the other geom_ functions.

Clip the contour with polygon using ggplot and R

I want to create a contour and then clip the contour by the polygon and only show the contour within the polygon.
Shapefile data can be found here
Csv file can be found here
The code I used is as follows:
library("ggplot2")
library("rgdal")
library("gpclib")
library("maptools")
require(sp)
age2100 <- read.csv("temp.csv",header=TRUE, sep=",")
shape.dir <- "C:/Users/jdbaba/Documents/R working folder/shape" # use your directory name here
lon.shape <- readOGR(shape.dir, layer = "Export_Output_4")
str(lon.shape)
lon.df <- fortify(lon.shape, region = "Id")
p <- ggplot(lon.df, aes(x = long, y = lat, group = group)) +
geom_polygon(colour = "black", fill = "grey80", size = 1) +
theme()
p <- p + geom_point(data=age2100,aes(x=age2100$x,y=age2100$y,group="z"),size=0.1)
p <- p + geom_density2d(colour="red")
p
Here, I have created the map, points and the contour. I don't know whether the code I am using created the contour for variable z or not. If it is not correct can anyone suggest me ?
The sample output that I got is as follows:
Now, I want to clip the contour within the polygon and hide the part of contour that is outside the polygon.
I want to know how to add the labels to the contour and control the contour interval.
Please let me know if my question is not clear.
Thanks
Jdbaba
I can't reproduce your map exactly. The code you provided gives me a map with two sets of contours - one that looks like yours and one that overlaps it in the southern part of the region. I suspect this is an artefact of your group setting. Also, I can see there is an island in the southern part of what I assume is the lake.
I like to clean up and partition my ggplot stuff into bits, since I often find something in an early part of a ggplot call confuses something in a later part. Here's how I would map the region, draw points, and then add a density contour:
map <- function(){
geom_polygon(data=lon.df,aes(x=long,y=lat,group=piece),colour="black",fill="grey80",size=1)
}
points <- function(){
geom_point(data=age2100,aes(x=x,y=y),size=0.1)
}
density <- function(){
geom_density2d(data=age2100,aes(x=x,y=y),colour="red")
}
ggplot()+map() +points() +density()
Which gives this:
Now that's much different to what your contour looks like, and I don't know why. Maybe your group parameter is grouping all the points with the same z?
Anyway, it seems you don't want a density plot, you want a map of your Z values over your area. This is going to need kriging or some other interpolation technique. Forget about ggplot for a while, concentrate on the numbers.
For starters, plot the points coloured by the z value. You should see this:
which at least will give you a good idea of what the correct contour will look like.
Anyway, this is getting into a full-on tutorial..

Resources