Why does coord_map produce a weird output? - r

I'm trying to draw a world map using ggplot. My code is in my gist file. The output is correct when I don't use coord_map but very strange when I use coord_map :
ggplot(data = test, aes(fill = x)) +
geom_map(aes(map_id = id), map =world.ggmap, color = "white") +
expand_limits(x = world.ggmap$long, y = world.ggmap$lat) +
theme_tufte() +
coord_map()
ggplot(data = test, aes(fill = x)) +
geom_map(aes(map_id = id), map =world.ggmap, color = "white") +
expand_limits(x = world.ggmap$long, y = world.ggmap$lat) +
theme_tufte()
I've got the same error when I use data from the maps package :
library(ggplot2)
library(maps)
world <- map_data("world")
ggplot() +
geom_map( data=world, aes(x=long, y=lat, group = group, map_id = region),colour="white", fill="grey10", map = world ) +
coord_map()
Does anyone has an answer ?

I had a similar problem before, due to longitude values outside the range [-180,180]. In your example the data do not have this problem but my trick seems to work also here. In my case I just used 'xlim' to exclude the problematic data.
This solution seems to work in your case also (I used the code from your gist):
map+coord_map(xlim=c(-180,180))
It produces the following map:
There is still a problem with Antarctica, you can also consider clipping it too if you don't need this area:
map+coord_map(xlim=c(-180,180), ylim=c(-60, 90))

Another solution is to use wrld_simpl from maptools instead, but it retains issues with Antarctica.
require(maptools)
require(ggmap)
md <- map_data("world2")
data(wrld_simpl)
ggplot(wrld_simpl, aes(group = group, x = long, y = lat)) +
geom_map() +
coord_map()

I'm sure that is quite late but the same problem is still happening in ggplot.
If you're trying to zoom-in use the following approach.
ggplot()+...+xlim(c(-100, -25))+ ylim(c(-60, 20))
Good luck!

Related

Mapping sampling sites on a map in R + creating a zoom in of a region in the same map

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.

Plotting both state AND county boundaries on same map using plot_usmap from usmap package in R

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')

Unwanted Horizontal Lines in Map Projection in R

A few lines of code to expose my problem. When I work with a map of
the world and I introduce a projection, I always end up with some
weird looking horizontal lines.
Please have a look at
https://www.rdocumentation.org/packages/ggplot2/versions/1.0.0/topics/coord_map
from where I take the example for New Zeland
library(ggplot2)
nz <- map_data("nz")
# Prepare a map of NZ
nzmap <- ggplot(nz, aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "white", colour = "black")
# Plot it in cartesian coordinates
nzmap
# With correct mercator projection
nzmap + coord_map()
which works beautifully. Now let us do the same with the world
world <- map_data("world")
# Prepare a map of the world
worldmap <- ggplot(world, aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "white", colour = "black")
# Plot it in cartesian coordinates
worldmap
##but the following is a disaster!
# With correct mercator projection
worldmap + coord_map()
I see this issue of the horizontal lines with a projection has been
going on for quite a while, but I was able to find only seasoned posts
and I had assumed this was fixed long ago.
Please find below my sessionInfo.
Is there any solution to this? Is it still an open bug?
This is a pretty common problem in ggplot, but happily it is easily fixed:
worldmap + coord_map(xlim=c(-180,180))
produces
solution from: Why does coord_map produce a weird output?

Edit boundaries in a map with ggplot2

I have created a map with ggplot2. So far I am happy with my plot but I was wondering whether it is possible to edit the boundaries that separate each of the regions within the map. I know that adding geom_path() you can explicitly incorporate them but I have not figured out how to edit the level of thickness. Is anyone familiar with how to do this? Many thanks in advance.
The code I have used is the following:
library(ggplot2)
library(RColorBrewer)
ex_sector = ggplot(data_mapping, aes(long, lat, group=group, fill = entry_cat)) +
scale_fill_brewer(type = "seq", palette = "Greens") + geom_polygon() + geom_path(colour = "black")
ggsave("test_fill.png", ex_sector, scale = 0.5)
An the output is:

Troubleshooting ggplot()/maps() Runtime Issue

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.

Resources