RGoogleMaps axes - r

I can't find any documentation of the following problem I'm having with the axis labels in RGoogleMaps:
library(RgoogleMaps)
datas <- structure(list(LAT = c(37.875, 37.925, 37.775, 37.875, 37.875),
LON = c(-122.225, -122.225, -122.075, -122.075, -122.025)),
.Names = c("LAT", "LON"), class = "data.frame",
row.names = c(1L, 2L, 3L, 4L, 5L))
# Get bounding box.
boxt <- qbbox(lat = datas$LAT, lon = datas$LON)
MyMap <- GetMap.bbox(boxt$lonR, boxt$latR, destfile = "Arvin12Map.png",
maptype = "mobile")
PlotOnStaticMap(MyMap, lat = datas$LAT, lon = datas$LON,
axes = TRUE, mar = rep(4, 4))
When I run this on my computer the horizontal axis ranges from 300W to 60E, but the ticks in between aren't linearly spaced (300W, 200W, 100W, 0, 100E, 160W, 60W).
Also, the vertical axis moves linearly from 300S to 300N. It seems that no matter what data I supply for datas, the axes are always labeled this way.
My question is:
1. Does this problem occur on other machines using this code?
2. Does anyone have an explanation for it?
and
3. Can anybody suggest a way to get the correct axes labels (assuming these are "incorrect", but maybe i'm somehow misinterpreting the plot!)?
Thank you for your time.

Yes
As #Andrie suggested, this appears to be a bug. When axes = TRUE, the degAxis() function called by PlotOnStaticMap() extracts the x and y plot coordinates of the pretty tickmarks found by axTicks(). degAxis() expects these coords to be in the coordinate system of the map, but rGoogleMaps returns them as pixel coordinates, calculated from a central origin. With a plot size of 640 x 640, the pretty tickmarks are assigned to -300, -200, -100, 0,100, 200, 300 in both E-W and N-S directions. You end up with 300W, 200W, 100W, 0, 100E, 160W, 60W, because the degreeLabelsEW() function called by degAxis() assumes that, given longitudes must fall within [-180, 180], any longitudes higher than 180 are in fact in the western hemisphere (e.g. 200E is 20 degrees eastward into the western hemisphere, i.e. 160W). Not sure why it doesn't perform similarly with nonsensical N, S and W coordinates.
A quick workaround, continuing with your MyMap object:
PlotOnStaticMap(MyMap, lat = datas$LAT, lon = datas$LON,
axes = FALSE, mar = rep(4.5, 4))
# x-axis
xrange <- MyMap$BBOX$ur[2] - MyMap$BBOX$ll[2]
xticklength <- xrange / (length(axTicks(1)) - 1)
xticklabs <- seq(MyMap$BBOX$ll[2], MyMap$BBOX$ur[2], xticklength)
xticklabs <- parse(text = paste(sprintf('%.2f', abs(xticklabs)),
ifelse(xticklabs < 0, '*degree*W', '*degree*E'), sep=''))
axis(1, at=axTicks(1), xticklabs, cex.axis=0.8)
# y-axis
yrange <- MyMap$BBOX$ur[1] - MyMap$BBOX$ll[1]
yticklength <- yrange / (length(axTicks(2)) - 1)
yticklabs <- seq(MyMap$BBOX$ll[1], MyMap$BBOX$ur[1], yticklength)
yticklabs <- parse(text = paste(sprintf('%.2f', abs(yticklabs)),
ifelse(yticklabs < 0, '*degree*S', '*degree*N'), sep=''))
axis(2, at=axTicks(2), yticklabs, cex.axis=0.8, las=1)

Related

Error: x,y coords given but no window specified (spatstat)

I am generating a landscape pattern that evolves over time. The problem with the code is that I have clearly defined a window for the object bringing up the error but the window is not being recognised. I also do not see how any points are falling outside of the window, or how that would make a difference.
library(spatstat)
library(dplyr)
# Define the window
win <- owin(c(0, 100), c(0, 100))
# Define the point cluster
cluster1 <- rMatClust(kappa = 0.0005, scale = 0.1, mu = 20,
win = win, center = c(5,5))
# define the spread of the points
spread_rate <- 1
new_nests_per_year<-5
years<-10
# Plot the initial cluster
plot(win, main = "Initial cluster")
points(cluster1, pch = 20, col = "red")
newpoints<-list()
# Loop for n years
for (i in 1:years) {
# Generate new points that spread from the cluster
newpoints[[1]] <-rnorm(new_nests_per_year, mean = centroid.owin(cluster1)$y, sd = spread_rate)
newpoints[[2]] <-rnorm(new_nests_per_year, mean = centroid.owin(cluster1)$x, sd = spread_rate)
# Convert the list to a data frame
newpoints_df <- data.frame(newpoints)
# Rename the columns of the data frame
colnames(newpoints_df) <- c("x", "y")
# Combine the new points with the existing points
cluster1_df <- data.frame(cluster1)
newtotaldf<-bind_rows(cluster1_df,newpoints_df)
cluster1<-as.ppp(newtotaldf, x = newtotaldf$x, y = newtotaldf$y,
window = win)
# Plot the updated cluster
plot(win, main = paste("Cluster after year", i))
points(cluster1, pch = 20, col = "red")
}
However, when I run line:
cluster1<-as.ppp(newtotaldf, x = newtotaldf$x, y = newtotaldf$y,
window = win)
I recieve the error:
Error: x,y coords given but no window specified
Why would this be the case?
In your code, if you use the command W = win it should solve the issue. I also believe you can simplify the command without specifying x and y:
## ...[previous code]...
cluster1 <- as.ppp(newtotaldf, W = win)
plot(win)
points(cluster1, pch = 20, col = "red")

Missing data/ 0 value for Chl-a on 180 degree meridian (Oceanmap)

My first querstion here, fantastic community.
I have a slight issue projecting some chl-a data across the 180 meridian (Fiji), using Oceanmap package. I can do this in GIS but would like to be able to produce these results in R. Please see below for code and images. Basically when I project a larger frame of the area I want to display the data projects perfectly, however when I zoom in closer to Fiji which is really what I want, I get a white line (0 value I assume) across the 180 meridian. Is this a coordinate projection issue and the stitching now working at such resolution?
library(oceanmap)
library(ncdf4)
library(raster)
library(viridis)
chl.win <- ('~/Desktop/A20200812020172.L3m_SNSP_CHL_chlor_a_4km.nc')
chl.dat <- nc_open(chl.win)
chl.dat.raster <- nc2raster(chl.dat, "chlor_a", lonname="lon", latname="lat", date=T)
chl.flip <- flip(chl.dat.raster, "y")
chl.360 <- shift(raster::rotate(shift(chl.flip, 180)), 180)
chl.360.crop = raster::crop(chl.360, extent(c(176, 183, -19.8, -15.5)))
vpal <- viridis(100, alpha = 1, begin = 0, end = 1, option = "mako")
v(chl.360.crop, cbpos = "r", pal = "jet", zlim = c(0,1), cb.xlab = expression("Chlorophyll-a (mg m"^-3*")"),
bwd = 0, grid = F, replace.na = F, Save = T, plotname = "First_Quarter_2020", fileformat = "png", width = 12,
height = 6)
Image showing white line on 180 meridian

Mapping bearing and speed of ocean currents

I have two matrices of bearing and speed data for ocean currents
bearings <- matrix(data = c(170.0833, 175.6863, 182.3538, 180.3335, 170.8965,
178.3276, 182.3693, 187.2196, 182.3533, 168.3498,
189.1664, 187.6813, 187.0393, 180.2259, 166.8412,
193.4223, 188.5367, 182.4128, 175.2626, 167.3058,
192.2930, 185.5073, 175.0302, 168.6284, 167.8392),
ncol = 5, nrow = 5, byrow = F)
speed <- matrix(data = c(0.1389173, 0.1585099, 0.1796583, 0.2021887, 0.2117295,
0.1196745, 0.1463118, 0.1637266, 0.1730471, 0.1804999,
0.1309982, 0.1546123, 0.1593298, 0.1517513, 0.1550037,
0.1621728, 0.1694083, 0.1606560, 0.1459710, 0.1457233,
0.1659898, 0.1535861, 0.1396885, 0.1294339, 0.1337756),
ncol = 5, nrow = 5, byrow = F)
I wanted to graph the direction of the current bearings with arrows, while the magnitude/speed of the current is represented by the length of the arrow, a bit something like these maps:
Wind stress figure taken from Shankar et al. 2002
I know the package oce may be able to do something like that, but it specifically works with different types of oceanographic data rather than matrices/data frames that I'm using.
Anyone happen to know how to do that? I have gotten as far as making them into raster objects using the raster() function from the raster library:
library(raster)
bearing.rst <- raster(bearings,
xmn = 66,
xmx = 67.3333,
ymn = 10.6667,
ymx = 12)
speed.rst <- raster(speed,
xmn = 66,
xmx = 67.3333,
ymn = 10.6667,
ymx = 12)
Ideally I'd do this with base R graphics, or with a package that plays nice with base R graphics (e.g. not ggplot2 or lattice).
Graph from:
Shankar, D., Vinayachandra, P.N., & Unnikrishnan, A.S. (2002). The monsoon currents in the north Indian Ocean. Progress in Oceanography, 52: 62-120. doi: 10.1016/S0079-6611(02)00024-1
with base R:
plot(bearing.rst) # your base map, I use this because I didn't have it
Get your starting coordinates:
arr.coor <- rasterToPoints(bearing.rst)
arr.coor <- cbind(arr.coor[,-3], bearing=c(t(bearings)), speed=c(t(speed)))
Calculate your finishing coordinates with trigonometric functions:
x1 <- arr.coor[,1] + arr.coor[,4] * cos(arr.coor[,3]*pi/180)
y1 <- arr.coor[,2] + arr.coor[,4] * sin(arr.coor[,3]*pi/180)
arr.coor <- cbind(arr.coor, x1, y1)
Plot your arrows:
arrows(arr.coor[,1],arr.coor[,2],arr.coor[,5],arr.coor[,6])
I guess the same principal could work with ggplot2. The idea is to get a table with all your arrows origin and end.
With ggplot
bearings <- c(170.0833, 175.6863, 182.3538, 180.3335, 170.8965,
178.3276, 182.3693, 187.2196, 182.3533, 168.3498,
189.1664, 187.6813, 187.0393, 180.2259, 166.8412,
193.4223, 188.5367, 182.4128, 175.2626, 167.3058,
192.2930, 185.5073, 175.0302, 168.6284, 167.8392)
speed <- c(0.1389173, 0.1585099, 0.1796583, 0.2021887, 0.2117295,
0.1196745, 0.1463118, 0.1637266, 0.1730471, 0.1804999,
0.1309982, 0.1546123, 0.1593298, 0.1517513, 0.1550037,
0.1621728, 0.1694083, 0.1606560, 0.1459710, 0.1457233,
0.1659898, 0.1535861, 0.1396885, 0.1294339, 0.1337756)
df <- data.frame(x = rep(1:5,5),
y = rep(1:5, each = 5),
bearings = bearings,
speed = speed)
df$dx <- sin((df$bearings)/360*pi*2)*df$speed
df$dy <- cos((df$bearings)/360*pi*2)*df$speed
ggplot(df, aes(x, y)) +
geom_segment(aes(xend = x + dx, yend = y + dy),
arrow = arrow(length = unit(0.1,"cm"))) +
theme_bw()

R maps - Filter coordinates out when plotting points in map

I have a large data frame of events locations (longitude, latitude). See a sample below:
events <- structure(list(lat = c(45.464944, 40.559207, 45.956775, 44.782831, 45.810287, 35.913357, 43.423855, 45.2359, 45.526025, 41.91371, 46.340833, 40.696482, 42.367164, 41.913701, 41.89167, 46.046206, 41.108316, 45.514132, 45.688118, 37.090387, 43.446555, 41.913712, 46.614833, 45.368825, 41.892168), lon = c(9.163453, 8.321587, 12.983347, 10.886471, 9.077844, 10.560439, 6.768272, 9.23176, 9.375761, 12.466994, 6.889444, 17.316925, 13.352248, 12.466992, 12.516713, 14.497758, 16.871019, 12.056176, 9.176543, 15.293506, 6.77119, 12.466993, 15.194904, 11.110711, 12.516085)), .Names = c("lat", "lon"), row.names = c(NA, 25L), class = "data.frame")
and I would like to plot only the events that happened in a given country (for instance, Italy).
The following plots all events:
library(rworldmap)
library(maps)
par(mar=c(0,0,0,0))
plot(getMap(resolution="low"), xlim = c(14,14), ylim = c(36.8,47))
points(x=events$lon, y=events$lat, pch = 19, col ='red' , cex = 0.6)
How can I filter out the events that fall outside the boundaries of the country ? Thank you in advance for help and support.
assign polygon map to an object:
m = getMap(resolution="low")
convert events into an sp object -- first longitude, then latitude:
pts = SpatialPoints(events[c(2,1)])
assign CRS:
proj4string(pts) = proj4string(m)
plot points inside any of the polygons:
points(pts[m,], pch = 3)
select points inside Italy:
it = m[m$ISO_A2 == "IT",]
points(pts[it,], col = 'blue')
(this uses sp::over, but behind the scenes)

Add a label to map at each leg start

I'm plotting legs of a route to a ggmap. It works okay so far. I've been trying to add a label containing the order (n from the loop) of each leg.
I've tried +geom_text to the geom_leg() but I get the error :
Error in geom_leg(aes(x = startLon, y = startLat, xend = endLon, yend = endLat), :
non-numeric argument to binary operator
I'd appreciate any help adding a label to indicate the leg.
Data :
structure(c("53.193418", "53.1905138631287", "53.186744", "53.189836",
"53.1884117", "53.1902965", "53.1940384", "53.1934748", "53.1894004",
"53.1916771", "-2.881248", "-2.89043889005541", "-2.890165",
"-2.893896", "-2.88802", "-2.8919373", "-2.8972299", "-2.8814698",
"-2.8886692", "-2.8846099"), .Dim = c(10L, 2L))
Function :
create.map<-function(lst){
library("ggmap")
cncat<-c(paste(lst[,1],lst[,2],sep=","))
df2<-data.frame(cncat)
leg <-function(start, dest, order){
r<- route(from=start,to=dest,mode = c("walking"),structure = c("legs"))
c<- geom_leg(aes(x = startLon, y = startLat,xend = endLon, yend = endLat),
alpha = 2/4, size = 2, data = r,colour = 'blue')+
geom_text(aes(label = order), size = 3)
return (c)
}
a<-qmap('Chester, UK', zoom = 15, maptype = 'road')
for (n in 1:9){
l<-leg(as.character(df2[n,1]), as.character(df2[n+1,1]),n)
a<-a+l
}
a
}
Is this close? (Note: this calls your list of points way.points).
way.points <- as.data.frame(way.points,stringsAsFactors=FALSE)
library(ggmap)
rte.from <- apply(way.points[-nrow(way.points),],1,paste,collapse=",")
rte.to <- apply(way.points[-1,],1,paste,collapse=",")
rte <- do.call(rbind,
mapply(route, rte.from, rte.to, SIMPLIFY=FALSE,
MoreArgs=list(mode="walking",structure="legs")))
coords <- rbind(as.matrix(rte[,7:8]),as.matrix(rte[nrow(rte),9:10]))
coords <- as.data.frame(coords)
ggm <- qmap('Chester, UK', zoom = 15, maptype = 'road')
ggm +
geom_path(data=coords,aes(x=startLon,y=startLat),color="blue",size=2)+
geom_point(data=way.points,aes(x=as.numeric(V2),y=as.numeric(V1)),
size=10,color="yellow")+
geom_text(data=way.points,
aes(x=as.numeric(V2),y=as.numeric(V1), label=seq_along(V1)))
So this assembles a vector of from and to coordinates using apply(...), then uses mapply(...) to call route(...) with both vectors, returning the overall list of coordinates in a data frame rte. Because the coordinates are stored as, e.g. $startLat and $endLat, we form a coords data frame by adding the final $endLat and $endLong to rte to get the very last leg of the route. Then we use geom_path(...) to draw the path in one step. Finally we use geom_text(...) with x and y-values from the original way.points data frame, and we use geom_point(...) just to make them stand out a bit.
Here's a bare bones solution. I just added the labels to the finished ggmap object a. If you replace the line
a
with
lst2 <- data.frame(cbind(lst, leg = as.character(1:10) )
names(lst2) <- c("lat", "lon", "leg")
a <- a + geom_text(data=lst2,aes(x=lon,y=lat,label=leg),size=5, vjust = 0, hjust = -0.5)
return(a)
in your create.map function, you should get (roughly) the desired result. I might have reversed the lat and lon variables, and you probably want to tweak the size, location, etc. Hope this helps!

Resources