Reputation: 222
I am having trouble in separating the legends in a ggplot2 graph with multiple layers. What my plot does is to fill different municipalities according to the number of textile companies present there and I also plot the plant localization with geom_point
. My guess is to use aes.override()
somehow, but I haven't been able to do this still. The solutions that I have read do not deal with a different variable for the plots detailed in the aes()
of geom_point()
.
If you want to test the code below, you could download the shapefile for the brazilian municipalities here, use readOGR
and fortify
, then choose to fill the municipalities with your preference with fill
and set arbitrarily random points within Brazil for geom_point()
creating a different variable, such as lat_plant
and long_plant
below. The region
column below details brazilian regions -- in this case, the "1" details the northern region of Brazil.
#setting the ggplot
library(ggplot2)
gg2 < -ggplot(data = out[out$region =="1",],
aes(x = long, y = lat, group = group, fill = as.factor(companies))) +
geom_polygon() +
ggtitle("title") +
scale_fill_discrete(name = "Number of Textile Companies") +
theme(plot.title = element_text(size = 30, face = "bold")) +
theme(legend.text = element_text(size = 12),
legend.title = element_text(colour = "blue", size = 16, face = "bold"))
#graph output
gg2 +
geom_point(data = out[out$region =="1",], aes(x = long_plant, y = lat_plant), color = "red")
What I am getting as legend is this:
And I would like to separate it, detailing that the dots as localizations and the colors as the filling for the number of textile companies in the region.
Upvotes: 0
Views: 396
Reputation: 23574
I leave another option for you. hmgeiger treated the number of textile companies as factor. But, I rather treated the variable as a continuous variable. Since there is NO reproducible data, I created a sample data by myself. Here, I created random samples uing longitude and latitude of Brazil, and made sure that some data points stay in Brazil. whatever2
contains data points staying in Brazil. I did a bit of trick here as well. I added a new column called Factory location
. This is the dummy variable for adding color to data points in the final graphic. hmgeiger created Dummy.var
that contains characters for you. I rather left ""
in this column since you may not want to see any text in legend.
For your legend issue, as Antonio mentioned and hmgeiger did, you need to add color in aes()
in geom_point()
. This solves it. I did a bit more thing for you. If you do not know how many factories exist in each municipal, you need to count the number of factories. I did the job using poly.count()
in the GISTools
package and created another data frame that contains the numbers of factories in each municipal.
When I drew the map, I had three layers. One is for the polygons and another for filling the polygons with colors. They are done with geom_cartogram()
from the ggalt
package. The key thing is that you need to have a common key column for map_id
. id
in the first geom_cartogram()
and ind
in the second geom_cartogram()
are identical information. In geom_point()
you need color
in aes()
. The legend has a continuous bar for the number of factories and a single dot for factory location. No text exists next to it. So this makes the legend tidy, I think.
library(raster)
library(tidyverse)
library(GISTools)
library(RColorBrewer)
library(ggalt)
library(ggthemes)
# Get polygon data for Brazil
brazil <- getData("GADM", country = "brazil", level = 1)
mymap <- fortify(brazil)
# Create dummy data staying in the polygons
# For more information: https://stackoverflow.com/questions/47696382/removing-data-outside-country-map-boundary-in-r/47699405#47699405
set.seed(123)
mydata <- data.frame(long = runif(200, min = quantile(mymap$long)[1], max = quantile(mymap$long)[4]),
lat = runif(200, min = quantile(mymap$lat)[1], max = quantile(mymap$lat)[4]),
factory = paste("factory ", 1:200, sep = ""),
stringsAsFactors = FALSE)
spdf <- SpatialPointsDataFrame(coords = mydata[, c("long", "lat")], data = mydata,
proj4string = CRS("+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"))
whatever <- spdf[!is.na(over(spdf, as(brazil, "SpatialPolygons"))), ]
whatever2 <- as.data.frame(whatever) %>%
mutate(`Factory location` = "")
# Now I check how many data points (factories) exist in each polygon
# and create a data frame
factory.num <- poly.counts(pts = whatever, polys = brazil)
factory.num <- stack(factory.num)
ggplot() +
geom_cartogram(data = mymap, aes(x = long, y = lat, map_id = id),
map = mymap) +
geom_cartogram(data = factory.num, aes(fill = values, map_id = ind),
map = mymap) +
geom_point(data = whatever2, aes(x = long, y = lat, color = `Factory location`)) +
scale_fill_gradientn(name = "Number of factories", colours = brewer.pal(5, "Greens")) +
coord_map() +
theme_map()
Upvotes: 4
Reputation: 131
FYI, the link you posted to download the shape file is quite slow, at least to download to a US computer.
This link has downloads that work a lot better, and also shows how to read in shape data: https://dioferrari.wordpress.com/2014/11/27/plotting-maps-using-r-example-with-brazilian-municipal-level-data/
I made an example using the regions rather than municipalities data to keep it simple.
Data I used available for download here: https://drive.google.com/file/d/0B64xLcn8DZfwakNMbHFLQWo4YzA/view?usp=sharing
#Load libraries.
library(rgeos)
library(rgdal)
library(ggplot2)
#Read in and format map data.
regions_OGR <- readOGR(dsn="/Users/hmgeiger/Downloads/regioes_2010",
layer = "regioes_2010")
map_regions <- spTransform(regions_OGR,CRS("+proj=longlat +datum=WGS84"))
map_regions_fortified <- fortify(map_regions)
#We make there be 0, 1, or 3 textile companies.
#map_regions_fortified is in order by ID (region).
#So, we add a column with the number of textile companies
#repeated the right number of times for how many of each region there is.
num_rows_per_region <- data.frame(table(map_regions_fortified$id))
map_regions_fortified <- data.frame(map_regions_fortified,
Num.factories = factor(rep(c(1,0,1,3,1),times=num_rows_per_region$Freq)))
#First, plot without any location dots.
ggplot()+geom_polygon(data=map_regions_fortified,
aes(x = long,y = lat, group=group, fill=Num.factories),colour="black")
Now, let's add the factory locations.
#Set latitude and longitude based on the number of factories per region.
factory_locations <- data.frame(long = c(-65,-55,-51,-44,-42,-38),
lat = c(-5,-15,-27,-7,-12,-8))
#Add a dummy variable, which then allows the colour of the dots
#to be a part of the legend.
factory_locations <- data.frame(factory_locations,
Dummy.var = rep("One dot = one factory location",times=nrow(factory_locations)))
#Replot adding factory location dots.
#We will use black dots here since will be easier to see.
ggplot()+geom_polygon(data=map_regions_fortified,
aes(x = long,y = lat, group=group, fill=Num.factories),colour="black")
+ geom_point(data = factory_locations,aes(x = long,y = lat,colour = Dummy.var))
+ scale_colour_manual(values="black") + labs(colour="")
#Bonus: Let's change the color vector to something more color-blind friendly.
mycol <- c("#E69F00", "#56B4E9", "#009E73", "#F0E442",
"#0072B2", "#D55E00", "#CC79A7","#490092")
ggplot()+geom_polygon(data=map_regions_fortified,
aes(x = long,y = lat, group=group, fill=Num.factories),colour="black")
+ geom_point(data = factory_locations,aes(x = long,y = lat,colour = Dummy.var))
+ scale_colour_manual(values="black") + labs(colour="")
+ scale_fill_manual(values=mycol)
Upvotes: 1