for my PhD project, I'd like to show my sampling sites (coordinates) on a map showing them first on a map of NZ and then building a zoom in of the region (coordinates that I pick myself) to show the sampling sites in that specific region. I am very new to R and I am finding a bit frustrating.
I managed to build a map of NZ (code follows) but how can I add the data points on it and how can I create a zoom in of a certain region and adding data points on it as well??
NZ <- map_data("nz",xlim = c(166, 179), ylim = c(-48, -34))
ggplot() +
geom_path(aes(long, lat, group=group), data=NZ, color="black") +
coord_equal() +
scalebar(NZ, dist = 100, dist_unit = "km", st.size=3, height=0.01, model = 'WGS84', transform = TRUE)
Thanks to whoever will help me!!
For example:
library(tidyverse)
dunedin <- tibble(X=170.5, Y=-45 - 52/60, Text="Dunedin")
NZ <- map_data("nz",xlim = c(166, 179), ylim = c(-48, -34))
ggplot() +
geom_path(aes(long, lat, group=group), data=NZ, color="black") +
geom_point(data=dunedin, aes(x=X, y=Y), colour="blue") +
geom_label(data=dunedin, aes(x=X, y=Y, label=Text), colour="blue", nudge_x=1) +
coord_equal()
Incidentally, scalebar isn't part of ggplot2, so your example isn't self-contained. That's not a major issue here, but could be in another situation.
I would like to create a map of the US showing both state and county boundaries (i.e. state boundaries in a different color). I typically do this using either shape files that I import or using ggplot2's map_data function. However, I face three obstacles.
1) I cannot install gdal and geos in my computing environment so that precludes the use of any shape files or GeoJSON files (my attempts to map county level shape files loaded using fastshp have not been successful but I'm open to any solution that can reproduce the map below but with state boundaries included).
2) I need to include Hawaii and Alaska, so that excludes the use of map_data from ggplot2.
3) I need the map to include both state AND county boundaries, which makes the use of usmap package problematic as its a wrapper function for ggplot2 but without the ease and general ability to customize to the level of a raw ggplot2 object.
4) Also, cannot make use of sf package bc it has a non R library dependency (units package depends on C library libudunits2).
What I need: A map that can project Alaska and Hawaii and display state and county boundaries using contrasting colors and I need to accomplish all this without resorting to any packages that rely on rgeos, rgdal, and/or units.
What I've tried thus far plot_usmap from the usmap package:
library(dplyr)
library(stringr)
library(ggplot2)
library(usmap)
library(mapproj)
devtools::install_github("wmurphyrd/fiftystater")
library(fiftystater)
county_data<-read.csv("https://www.ers.usda.gov/webdocs/DataFiles/48747/PovertyEstimates.csv?v=2529") %>% #
filter(Area_name != "United States") %>%
select(FIPStxt, Stabr, Area_name, PCTPOVALL_2017) %>%
rename(fips = FIPStxt)
crimes <- data.frame(state = tolower(rownames(USArrests)), USArrests)
state_map <- map_data("state")
plot_usmap(data = county_data, values = "PCTPOVALL_2017", color = "white") +
geom_map(data = crimes, aes(map_id = state), map = fifty_states, color= "red") +
geom_path(data = state_map, aes(x =long , y=lat), color= "red")+
expand_limits(x = fifty_states$long, y = fifty_states$lat) +
theme(legend.position = "none") +
theme_map() #no go
plot_usmap(data = county_data, values = "PCTPOVALL_2017", color = "white") +
geom_map(data = crimes, aes(map_id = state), map = fifty_states, color= "red") +
expand_limits(x = fifty_states$long, y = fifty_states$lat) +
theme(legend.position = "none") +
theme_map() #no go
plot_usmap(data = county_data, values = "PCTPOVALL_2017", color = "white") +
geom_map(data = crimes, aes(map_id = state, color= "red"), map = fifty_states) +
expand_limits(x = fifty_states$long, y = fifty_states$lat) +
theme(legend.position = "none") +
theme_map() #no go
What I suspect is happening is that one layer (the original ggplot code) is projected using a different CRS system than the other layer -generated by plot_usmap. That second layer results in a very small red dot (see circle in map below). Not sure how to re-project without geos/gdal installed. See the map below with the black circle highlighting where the red dot is.
Ok after some suggestions from the package author and some of my own tinkering around I was finally able to get my desired output.
This approach is ideal for folks looking to generate a US map w/ Alaska and Hawaii included who...
1) Do not have the ability to install non-R packages in the
environment their R engine is running on (e.g. lack admin access)
2) Need to map both county and state boundaries using contrasting
colors
library(dplyr)
library(ggplot2)
library(usmap)
#Example data (poverty rates)
county_data<-read.csv("https://www.ers.usda.gov/webdocs/DataFiles/48747/PovertyEstimates.csv?v=2529") %>% #
filter(Area_name != "United States") %>%
select(FIPStxt, Stabr, Area_name, PCTPOVALL_2018) %>%
rename(fips = FIPStxt)
states <- plot_usmap("states",
color = "red",
fill = alpha(0.01)) #this parameter is necessary to get counties to show on top of states
counties <- plot_usmap(data = county_data,
values = "PCTPOVALL_2018",
color = "black",
size = 0.1)
Using the layers meta info already embedded in the data from us_map
ggplot() +
counties$layers[[1]] + #counties needs to be on top of states for this to work
states$layers[[1]] +
counties$theme +
coord_equal() +
theme(legend.position="none") +
scale_fill_gradient(low='white', high='grey20') #toggle fill schema using vanilla ggplot scale_fill function
Using just the raw data obtained from the us_map package
ggplot() +
geom_polygon(data=counties[[1]],
aes(x=x,
y=y,
group=group,
fill = counties[[1]]$PCTPOVALL_2018),
color = "black",
size = 0.1) +
geom_polygon(data=states[[1]],
aes(x=x,
y=y,
group=group),
color = "red",
fill = alpha(0.01)) +
coord_equal() +
theme_map() +
theme(legend.position="none") +
scale_fill_gradient(low='white', high='grey20')
Alright, so I'm struggling a bit in creating this map. The following code gives me this map, which is the map that I really want to use.
map(database= "world", ylim=c(15,90), xlim=c(-180,-24), fill = TRUE, projection = 'gilbert')
This is the code I used to save the map information.
map.dat <- map_data(map(database= "world", ylim=c(15,90), xlim=c(-180,-24), fill = TRUE, projection = 'gilbert'))
Now, when I run the following code, it gives me the error 'Error in eval(expr, envir, enclos) : object 'group' not found'. I'm not sure what that means.
ggplot(map.dat, aes(x=long, y=lat, group=group, fill=region)) +
geom_polygon() +
geom_point(data = basindf, aes(x = basindf$latitude, y = basindf$longitude)) +
theme(legend.position = "none")
I had set 'group = NULL' and 'fill = NULL' and that seems to allow me to plot, but it only displays this, which is not what I want. The map is gone!
What can I do to fix this? Also, I want to move away from the points and create lines. How would I be able to make lines based on a certain id?
EDIT: Seems that some of you needed basindf to troubleshoot. I've added the first 20 lines below.
"","id","year","month","date","basin","latitude","longitude","wind speed"
"1","1902276N14266",1902,"October",1902-10-03,"EP",-93.8,14,30
"2","1902276N14266",1902,"October",1902-10-03,"EP",-94,14.5,30
"3","1902276N14266",1902,"October",1902-10-03,"EP",-94.2,15,30
"4","1902276N14266",1902,"October",1902-10-03,"EP",-94.3,15.5,30
"5","1902276N14266",1902,"October",1902-10-04,"EP",-94.4,16,30
"6","1902276N14266",1902,"October",1902-10-04,"EP",-94.5,16.5,30
"7","1902276N14266",1902,"October",1902-10-04,"EP",-94.6,17,30
"8","1902276N14266",1902,"October",1902-10-04,"EP",-94.7,17.5,30
"9","1902276N14266",1902,"October",1902-10-05,"EP",-94.8,18,30
"10","1902276N14266",1902,"October",1902-10-05,"EP",-94.9,18.5,30
"11","1902276N14266",1902,"October",1902-10-05,"NA",-94.9,18.7,35
"12","1902276N14266",1902,"October",1902-10-05,"NA",-94.7,18.8,45
"13","1902276N14266",1902,"October",1902-10-06,"NA",-94.4,18.9,55
"14","1902276N14266",1902,"October",1902-10-06,"NA",-94,19.1,60
"15","1902276N14266",1902,"October",1902-10-06,"NA",-93.7,19.3,65
"16","1902276N14266",1902,"October",1902-10-06,"NA",-93.3,19.5,75
"17","1902276N14266",1902,"October",1902-10-07,"NA",-92.9,19.7,85
"18","1902276N14266",1902,"October",1902-10-07,"NA",-92.5,20,90
"19","1902276N14266",1902,"October",1902-10-07,"NA",-92,20.3,90
"20","1902276N14266",1902,"October",1902-10-07,"NA",-91.5,20.7,90
You have two main problems.
First, the error you are getting is because you are sepecufying aes() in the ggplot() call which means that those values inherit to all layers. That means it's trying to set a group= in the geom_point layer as well but you do not have groups for that layer. You can disable the inherited aesthetics with
ggplot(map.dat, aes(x=long, y=lat, group=group, fill=region)) +
geom_polygon() +
geom_point(data = basindf, aes(x = basindf$latitude, y = basindf$longitude), inherit.aes=FALSE) +
theme(legend.position = "none")
or you can sepecy the aes per layer
ggplot(map.dat) +
geom_polygon(aes(x=long, y=lat, group=group, fill=region)) +
geom_point(data = basindf, aes(x = basindf$latitude, y = basindf$longitude)) +
theme(legend.position = "none")
Your other problem is that you transformed your map data with a projection but not your point data.
You can transform your data with mapproj so they are both on the same scale
ggplot(map.dat) +
geom_polygon(aes(x=long, y=lat, group=group, fill=region)) +
geom_point(data = data.frame(mapproject(basindf$latitude, basindf$longitude, "gilbert")), aes(x = x, y = y)) +
theme(legend.position = "none")
This gives
The reason it was not working was because you set global aes parameters in the first call to aes, and ggplot2 was looking for group and region in the geom_points call to group and fill the points.
This technically works:
library(maps)
library(ggplot2)
ggplot() +
geom_polygon(data = map.dat, aes(x =long, y = lat, group = group, fill = region)) +
geom_point(data = basindf, aes(x = latitude, y = longitude)) +
theme(legend.position = "none")
You can see your map in the bottom right, very tiny. You want to rescale your map to lat/long, or your data to whatever you have in your map.
EDIT see the answer from #MrFlick for plot rescaling.