I downloaded level-0 US map (National border) in R(sf) format from https://gadm.org/download_country_v3.html. I plotted US border (level 0) as follows:
library(tidyverse)
us0 <- readRDS("<file.path>\\gadm36_USA_0_sf.rds")
ggplot() +
geom_sf(data = us0, size = 1, color = "steelblue", fill = NA)
Resultant image shown below
I would like to remove outlying islands A and B, and move Alaska from C to C'.
I tried but failed to extract longitude and latitude data from us0. I searched online but did not find adequate answers on how to do this in R. I would like to know how longitude and latitude data could be extracted from us0 with R so that I can freely delete A and B and remove C. Thank you.
using the raster package and the geom() function you can extract the raw coordinates from the RDS object, as well as which island/state the coordinate is part of and whether it is solid or a hole.
In your case:
geom(us0)
Then it's just a matter of finding out which vertices belong to which islands. A quick way of deleting B would be to delete everything with a positive x coordinate. You'll need to find out which objects correspond to Alaska if you're to move and scale it. The top of Hawaii is (i.i.r.c) lower down than the bottom of the Florida Keys so you can also get away with removing everything with a latitude less than 23.
Also, I suspect many Hawaiians would object to Hawaii being referred to as an outlying island....
Related
library(geodata)
ct_shp <- geodata::gadm('USA', level = 0, path=".")
plot(ct_shp)
When I plot the USA, I get this.
Any raster I plot for US using this shapefile as a basemap becomes really small. The only solution I have is to crop out polygons greater than 100 degrees longitude so that I get a bigger map of US and I can plot any US specifc raster for more appealing maps. I wondered if there's anyone who faces such issue and how they have dealt with it.
In this case I would first simplify the geometries a bit (that speeds things up, but is otherwise not related to your question).
library(geodata)
usa <- geodata::gadm('USA', level = 0, path=".")
usa <- simplifyGeom(usa, 0.01)
You can select the western hemisphere (or any other area) like this
e <- ext(-180, -60, 11, 78)
p <- crop(usa, e)
Alternatively, you can use rotate to eastern hemisphere bit so that it connects to the western hemisphere. For that you need "terra" >= 1.6-21 (currently the development version, you can install it with install.packages('terra', repos='https://rspatial.r-universe.dev'))
r <- rotate(usa, long=0, split=T)
plot(r)
This is still not a great basemap for the USA. There is a lot of whitespace and Alaska is way too big for most purposes. I would either use an appropriate (conical) map projection, or cut, resize, and move Alaska and Hawaii, but that is quite involved.
I've just started with mapping in R and I've managed to convert a lat, lon dataframe to a raster file and then plot state borders on top of that.
Now I need to get it ready to publish and would like to include only the shape of my 13-state region (and no great lakes).
library(tmap)
usa <- st_as_sf(maps::map("state", fill=TRUE, plot =FALSE))
map_us<- tm_shape(usa)+
tm_borders()
tm_shape(raster_file) +
tm_raster(style = "cont", palette = "viridis", midpoint = 0)+
map_us
I'm having a hard time finding something out there that would provide a polygon for multiple states and I have been through a lot of mapping packages. Sorry I can't include my raster data here.
To crop a raster file to {sf} vector shape you have in principle two options:
crop at data level; this involves raster::mask() with possibly raster::crop() later to reduce the extent of the raster (masked raster retains the original size)
retain the data, and overlay a white polygon with a hole over your plot
Cropping on data level is more "pure", but will leave you with ragged edges (a raster cell has to be square).
Overlaying a white polygon is not so pure, but might be preferable if your key aim is a slick presentation (and purity of essence be damned...)
You will find both of them discussed, together with examples and sample code, in this post on the RStudio community site.
I'm still somewhat new to R and the sf package...
I have two sets of multipolygon data that I am trying to analyze. My first set of polygons (fires) contains hundreds of wildfire perimeters. The second set (towns) contains hundreds of urban areas boundaries.
For each fire, I would like to calculate the distance to the closest town (fire polygon edge to closest town polygon edge), and add that as a field to each fire.
So far I have mostly been using the sf package for spatial data. In my searches, I can only find minimum distance methods for polygons to points, points to points, lines to points, etc. but cannot seem to find polygon to polygon examples. Any help to send me in the right direction would be much appreciated! Thank you.
#TimSalabim Thank you for sending me in the right direction. I was able to accomplish what I was after. Maybe not the most elegant solution, but it worked.
# create an index of the nearest feature
index <- st_nearest_feature(x = poly1, y = poly2)
# slice based on the index
poly2 <- poly2 %>% slice(index)
# calculate distance between polygons
poly_dist <- st_distance(x = poly1, y= poly2, by_element = TRUE)
# add the distance calculations to the fire polygons
poly1$distance <- poly_dist
I am trying to use a modified version of the R code found in the following link:
Latitude Longitude Coordinates to State Code in R
To test the code, I created the following formal arguments:
mapping = "state"
pointsDF = data.frame(x = c(-88.04607, -83.03579), y = c(42.06907, 42.32983))
latlong2state(pointsDF, mapping)
The code returned the following:
[1] "Illinois" NA
The first coordinate set returns a correct answer, i.e. "Illinois". However, when I input the 2nd coordinate set (i.e. -83.03579, 42.32983) into an online converter, I get the following:
Downtown, Detroit, MI, USA
(http://www.latlong.net/Show-Latitude-Longitude.html)
Running the code again but changing the second coordinate from 42.32983 to 43.33 puts the point in the state of Michigan.
When using the "world" map as my formal argument for the "mapping" variable, the code returns "USA". I have been struggling for days to figure this out and have had no luck. I have played around with SpatialPointDataFrames, various projections, and looked into the state polygon objects themselves. I am using R version 3.3.1 on a Windows 7 system. I think the data point in question may be falling on a border line. In which case, I think an "NA" would be expected. The code I used is below.
Code Used:
library(sp)
library(maps)
library(maptools)
library(rgdal)
latlong2state = function(pointsDF, mapping) {
local.map = map(database = mapping, fill = TRUE, col = "transparent", plot = FALSE)
IDs = sapply(strsplit(local.map$names, ":"), function(x) x[1])
maps_sp = map2SpatialPolygons(map = local.map, ID = IDs,
proj4string = CRS("+proj=longlat +datum=WGS84"))
pointsSP = SpatialPoints(pointsDF,
proj4string = CRS("+proj=longlat +datum=WGS84"))
indices = over(x = pointsSP, y = maps_sp)
mapNames = sapply(maps_sp#polygons, function(x) {x#ID})
mapNames[indices]
}
I am only two months in to learning R and love the language thus far. This has been the first time I could not find an answer. I would really appreciate an help provided on the matter!!!
Firstly, the issue is not due to the point lying on a border. In fact, over() would not return NA for a point on a border, but rather "if a point falls in multiple polygons, the last polygon is recorded."
NA denotes a point that does not fall in a polygon. We can zoom in on your map to see this is the case
plot(local.map, xlim = c(-83.2, -82.8), ylim=c(42.2,42.6), type="l")
polygon(local.map, col="grey60")
points(local.map)
points(pointsDF[2,], col="red")
The point falls outside the contiguous USA in Canada, according to the polygons provided by maps::map(). Why would this be the case when other maps, as you say, locate this point on the USA side of the border? I do not think this is a projection issue, because we are using the same WGS84 geographic coordinates for the polygons and the points. It seems, therefore, that the polygons themselves that are provided by maps::map() may be wrong.
We can check this by comparing to polygons from another source. I downloaded the US census departments highest resolution state boundaries from http://www2.census.gov/geo/tiger/GENZ2015/shp/cb_2015_us_state_500k.zip. Then,
shp.path <- "C:/Users/xxx/Downloads/cb_2015_us_state_500k/cb_2015_us_state_500k.shp"
states <- readOGR(path.expand(shp.path), "cb_2015_us_state_500k")
plot(states, xlim = c(-83.2, -82.8), ylim=c(42.2,42.6))
points(pointsDF[2,], col="red")
gets us this map in which we see that the point is inside the US boundary:
The solution I recommend therefore, is to use these better resolution, more reliable boundary polygons, particularly if you are interested to accurately resolve points close to borders.
I have some data which consists of time-stamped lat/lon pairs, a subset of which I've mapped out below using ggmap. If I wanted to select only the data consisting of travel along the highways, which you can kinda see on the map - the 280 running NW-SE between the green mountains and the grey flat area & the 101 cutting through the middle of the grey flat area (where the red is dense) - how would I select only that data?
What I'd ultimately like to achieve is a dataframe which contains only the highway/interstate travel. I've seen this question, which is a brief sketch of a possible solution in javascript, & suggests to use the Directions API to return the nearest road for any given point. I could then filter those results, but I'm wondering if anyone has found a cleaner solution.
Here's some sample data (CSV)
Here's the code to plot the above:
require(ggmap)
map<-get_googlemap(center="Palo Alto", zoom = 10)
ggmap(map) + geom_point(data = sample, aes(x = lon, y = lat),size = 3, color = "red")
You don't need an API key to run the above.
I just found this post and thought this is an interesting question. I wanted to download your sample data file. Unfortunately, the link was not working any more. Therefore, I could not try the whole process I had in my mind. However, I believe the following will let you move forward if you still try to do this task.
I recently noticed that Natural Earth offers road data. That is, you can get long and lat for the roads in the US, for example. If you can compare lon/lat in your data set and lon/lat of the road data, and identify matches in data points, you can get the data you want. My concern is to what extent your data points are accurate. If lon/lat perfectly stays on the road you are interested in, you will be OK. But if there are some margins, you may have to think how you can filter your data.
What I would like to leave here is evidence that the road data and googlemap match pretty well. As long as I see the output, the road data is reliable. You can subset your data using the road data. Here is my code.
### Step 1: shapefile becomes SpatialLinesDataFrame.
foo <- readShapeLines("ne_10m_roads_north_america.shp")
### Step 2: If necessary, subset data before I use fortify().
### dplyr does not work with SpatialLinesDataFrame at this point.
CA <- foo %>%
subset(.,country == "United States" & state == "California")
### Step 3: I need to convert foo to data frame so that I can use the data
### with ggplot2.
ana <- fortify(CA)
### Step 4: Get a map using ggmap package
longitude <- c(-122.50, -121.85)
latitude <- c(37.15, 37.70)
map <- get_map(location = c(lon = mean(longitude), lat = mean(latitude)),
zoom = 12, source = "google",
maptype = "satellite")
ggmap(map) +
geom_path(aes(x = long, y = lat, group = group), data = ana)