R: Displaying text in plot as legend - r

I have a map with 60 towns to be plotted.
I want to display the name of the towns but it is too cluttered. Is there a way I could number them and display the names as the legend like below?
I have tried "textxy" function from "calibrate" package but it displays only on the map.
Thanks!

Use the package ggmap. It allows you to get a base map and use ggplot functions to plot coordinates on top of the map. Here is a reproducible example:
library(ggmap)
library(dplyr)
# Get the base map
nevada <- get_map(location = 'nevada', maptype = "satellite", source = "google", zoom = 6)
# View the basemap
ggmap(nevada)
# Create data frame with cities and lat/long and an index
cities <- data.frame(city = c("Las Vegas", "Caliente", "Elko"),
lat = c(36.169941, 37.614965, 40.832421),
long = c(-115.13983, -114.511938, -115.763123))
cities <- cities %>% mutate(index = seq.int(nrow(cities)))
# Map with legend, colored by city
ggmap(nevada) +
geom_point(data = cities, aes(x = long, y = lat, color = paste(index, city)), cex = 3) +
labs(color = "cities") +
geom_text(data = cities, aes(x = long, y = lat, label = index), hjust = 2, color = "white")
If you want all the cities to be colored the same, use fill = city instead of color = city and specify the color (e.g. color = "red") outside of aes().
# Map with legend, all cities same color
ggmap(nevada) +
geom_point(data = cities, aes(x = long, y = lat, fill = city), cex = 3, color = "red") +
labs(fill = "cities") +
geom_text(data = cities, aes(x = long, y = lat, label = index), hjust = 2, color = "white")

Related

Reprojecting longitude and latitude coords within a dataframe to a mollweide projection for Ratite biogeographical distribution

I'm struggling to find a way to reproject the co-ordinates of my dataframe so I can plot them into a different projection. When I do all points collapse towards 0,0. so I take it the map itself is projecting towards my desired projection but the data aren't in the correct crs or don't have a crs?
The dataframe is all from the palaeobiology database, I downloaded all Palaeognathae occurance data and it contains, Genus, species, long, lat, paleolat, paleolong, cc.
Here is a link to my dataset: https://github.com/aamirrr-m/palaeognathae/blob/3ed0d951ba5968be67fdc95793ed3c52c8025386/Palaeognathae_Occurance_dataRevised.csv
**so far I can create a map with the mollweide projection without any datapoints **
(https://i.stack.imgur.com/lJQA5.png)
without any projection it works fine and it outputs this:
(https://i.stack.imgur.com/jxght.png)
when I attempt to add the data this is what returns:
(https://i.stack.imgur.com/6820D.png)
(Dooes not let me post images bc i have less than 10 rep)
so I tried adding coord_sf with the projection [using coord_sf(crs = "+proj=moll")] or something similar. this was added to the final ggplot at the bottom of the code block.
I do know some form of transformation must be done first, just need some help in knowing how to do it.
my code is as follows:
dput(ratites)
library(maps)
library(dplyr)
library(ggplot2)
library(sf)
library(rnaturalearth)
library(rnaturalearthdata)
#install.packages("ggthemes")
library(ggthemes)
library(mapproj)
library(tidyverse)
library(sp)
#projection of earth for plotting####
world <- ne_countries(scale = "medium", returnclass = "sf")
class(world)
attach(ratites)
#Mollweide projection
world %>%
st_transform(crs = "+proj=moll") %>%
ggplot() +
geom_sf() +
geom_sf()
theme_map()
#Preparing the data####
#this cleasn the data using the tidyverse pipe function selecting
#only the rows and columns you want to use
Ratite_C <- ratites %>%
select(accepted_name, Longitude, latitude, early_interval, cc)
#subsetting the data####
#they have all now been separated by time bin
Cret <- subset(Ratite_C, early_interval == "Cretaceous")
Paleo <- subset(Ratite_C, early_interval == "Paleocene")
Eoc <- subset(Ratite_C, early_interval == "Eocene")
Oligo <- subset(Ratite_C, early_interval == "Oligocene")
Mioc <- subset(Ratite_C, early_interval == "Miocene")
Plio <- subset(Ratite_C, early_interval == "Pliocene")
#these two have been combined to show recent ratite biogeography
Pleis.Holo <- subset(Ratite_C, early_interval == "Pleistocene" | early_interval == "Holocene")
#replotting the map data
R.Smap <- ggplot() +
geom_sf(data = world, color = "black", fill = "white", ) +
geom_point(data = Cret, aes( x = Longitude, y = latitude), size = 3,
shape = 23, fill = "orange") +
geom_point(data = Paleo, aes( x = Longitude, y = latitude), size = 3,
shape = 21, fill = "lightblue") +
geom_point(data = Eoc, aes( x = Longitude, y = latitude), size = 3,
shape = 21, fill = "goldenrod4") +
geom_point(data = Oligo, aes( x = Longitude, y = latitude), size = 3,
shape = 21, fill = "yellow") +
geom_point(data = Mioc, aes( x = Longitude, y = latitude), size = 3,
shape = 21, fill = "purple") +
geom_point(data = Plio, aes( x = Longitude, y = latitude), size = 3,
shape = 21, fill = "green") +
geom_point(data = Pleis.Holo, aes( x = Longitude, y = latitude), size = 2,
shape = 21, fill = "cyan") +
theme(panel.grid.major = element_blank(),panel.grid.minor = element_blank(),
panel.background = element_rect(fill = 'azure2'))`
R.Smap

How can I add names of cities and centroids in maps in R with maptools, ggplot or other packages?

I am trying to incorporate labels of provinces, and cities with labels and dots into a South African map.I can get a map with provincial subdivisions from a spdf file, from website https://gadm.org/download_country_v3.html
SA1spdf <- readRDS("gadm36_ZAF_1_sp.rds")
And I am trying to use the information in the slot:
SA1spdf#data#ADM1_EN
that contains the label of the 9 provinces
I want to place the labels in the center of the polygons, if possible, so I got the centroids of the 9 provinces:
centroids_SAdf <- as.data.frame(coordinates(SA1spdf))
and change names V1 and V2 to Longitude and Latitude
names(centroids_SAdf) <- c("Longitude", "Latitude")
Also I want to add a few cities to the plot:
coordinates_cities <- data.frame(city = c("Cape Town", "Durban", "Johannesburg", "Port Elizabeth"),lat = c(-33.930, -29.870, -26.190, -33.960 ), lon = c(18.460, 30.990, 28.040,25.590 )
but I cannot link all these together.
I can get a map with:
qtm(SA1spdf, fill = "white")
Using maptools and the following codes all return error messages
qtm(SA1spdf, fill = "white") + tm_text("SA1spdf$data#ADMN1_EN")
tm_shape(SA1spdf) + tm_polygons() + tm_fill(col = "white")
I dont get a white filled map, its filled with grey colour
the following codes return error messages:
tm_shape(SA1spdf) + tm_polygons() + tm_text(c("Eastern Cape","Free State" , "Gauteng","KwaZulu-Natal", "Limpopo","Mpumalanga","North West","Nothern Cape","Western Cape"))
ggplot(SA1spdf, aes(x = lon, y = lat), group = group) + geom_polygon(fill = "white") + geom_point(data = coordinates_cities, aes(x = lat, y = lon)) + geom_text(data= coordinate_cities, aes(label = city))
library(sp)
library(ggplot2)
library(tmap)
library(rgeos)
I'll use the same object SA1spdf you created with data from ZAF as sp object from GADM
coordinate_cities <- data.frame(
city = c("Cape Town", "Durban", "Johannesburg", "Port Elizabeth"),
lat = c(-33.930, -29.870, -26.190, -33.960),
long = c(18.460, 30.990, 28.040,25.590))
base plot
plot(SA1spdf)
points(coordinate_cities$lon, coordinate_cities$lat, pch = 16, col = "red", cex = 1)
text(coordinate_cities$lon, coordinate_cities$lat, coordinate_cities$city, adj = c(0, 0), cex = 0.7)
title(main = "South Africa", sub = "Main cities")
ggplot2
sa_df <- fortify(SA1spdf)
#> Regions defined for each Polygons
ggplot(sa_df, aes(long, lat)) +
geom_polygon(aes(group = group), fill = "white", colour = "black") +
geom_point(data = coordinate_cities, aes(x = long, y = lat), colour = "red") +
geom_text(data = coordinate_cities, aes(label = city), vjust = -1) +
coord_equal()
tmap
# convert coordinate_cities to sp object
sa_cities_spdf <- SpatialPointsDataFrame(coords = coordinate_cities[, c("long", "lat")],
data = coordinate_cities[, "city", drop = FALSE],
proj4string = CRS("+proj=longlat +datum=WGS84"))
tm_shape(SA1spdf) +
tm_borders() +
tm_layout(main.title = "South Africa regions") +
tm_text("NAME_1", size = 0.7) +
tm_shape(sa_cities_spdf) + tm_symbols(size = 0.5, col = "red")
Created on 2021-06-17 by the reprex package (v0.3.0)

Plotted points in Map doesn't vary based on the price

I plotted some data points on a map. The Map is the bounty King in Washington. I plotted them on the map successfully. My dataset consists of a column called prices. Their values range in between 0-800000.
I created a new column, called MapColor to print the value either as red or blue based on the price value. If price> 400000 red, else blue.
Now when plotting the points in the map, if MapColor is red I need to map it as red points and if not black. This is how I tried it. But the colors are plotting black only. This is what I tried
long <- c(47.5112,47.7210 ,47.3684)
lat <- c(-122.257, -122.319, -122.031)
price <- c(287655,456355,662500,234563)
House <- data.frame(long, lat, price)
House$MapColor <- ifelse(House$price >=400000, "red", "black")
col <- as.character(House$MapColor)
states <- map_data("state")
wa_df <- states %>%
filter(region == "washington", subregion == 'king')
counties <- map_data("county")
wa_county <- counties %>%
filter(region == "washington")
wa_base <-
ggplot(data = wa_df,
mapping = aes(x = long, y = lat, group = group)) + geom_point(data = House,aes(x = long, y = lat),size = 0.5,inherit.aes = FALSE) +
coord_fixed(1.3) +scale_color_manual(values=col)+
geom_polygon(color = "black", fill = "gray")
#geom_point(data = House, mapping = aes(x = long, y = lat), color = "red")
wa_base + theme_nothing() +
geom_polygon(data = wa_county, fill = NA, color = "black") +
geom_polygon(color = "black", fill = NA) # get the state border back on top
Please let me know if this is what you had in mind.
I think long and lat for those example points were reversed. I set the colors as either red or blue as per the description.
It maps the state polygon, then county, then adds the points using color = House$MapColor.
library(ggplot2)
library(ggmap)
lat <- c(47.5112, 47.7210, 47.3684)
long <- c(-122.257, -122.319, -122.031)
price <- c(287655, 456355, 662500)
House <- data.frame(long, lat, price)
House$MapColor <- ifelse(House$price >= 400000, "red", "blue")
wa_df <- map_data("state") %>%
filter(region == "washington")
wa_county <- map_data("county") %>%
filter(region == "washington")
ggplot(data = wa_df, mapping = aes(x = long, y = lat, group = group))+
geom_polygon(color = "black", fill = NA)+
geom_polygon(data = wa_county, fill = NA, color = "black")+
geom_point(data = House, mapping = aes(x = long, y = lat), color = House$MapColor)+
coord_fixed(1.3)+
theme_nothing()

Secondary legend on chloropleth for points and polygons, ggplot

I have a map with polygons and points on it - showing countries of interest in the world.
I want legends for both items (points and polygons), but can't add them. The polygon is plotted first (and so has a legend), while the points do not appear on the legend. To try and address this i add
show.legend = T
However the legend then adds the dots on top of the polygon colors as below:
What i want is another legend item with a yellow dot, where i can set the label as i want.
At the moment i am generating the points layer using a separate file. Perhaps i need to do this all from one df with points and polygons included - to generate the points and polygons from a single aes. But i can't think how to do this given my points have no group number.
Here is my code as it stands:
world <- map_data("world")
countries <- read_excel("country_table.xlsx", sheet = 3) #table of coutries with interest
world3 <- merge(world, countries, all.x = TRUE) %>%
arrange(order)
world4 <- world3 %>%
filter(!is.na(interest))
city <- read_excel("country_table.xlsx", sheet = 4) #point data
city$long <- as.numeric(city$long)
city$lat <- as.numeric(city$lat)
ggplot() +
geom_polygon(data = world3, aes(x = long, y = lat, group = group),
fill = "light grey") +
geom_polygon(data = world4, aes(x = long, y = lat, group = group, fill = interest),
col = "white") +
scale_fill_manual(name = "Interest/Support:",
breaks = c("interest", "past", "current"),
values = c(interest = "#a7ef88", past = "#3a7f1d", current = "#1b5104"),
labels = c("interest", "past", "current")) +
theme_map() +
theme(legend.position = "bottom") +
coord_fixed(xlim = c(-130, 160),
ylim = c(-50, 75),
ratio = 1.4) +
geom_point(data = city, aes(x= long, y = lat),
shape = 21, inherit.aes = F, size = 2, col = "black", fill = "yellow", show.legend = T)
Any thoughts?
Final code for the ggplot section posted below. Thanks to aosmith.
ggplot() +
#create base plot all polygons in grey
geom_polygon(data = world3, aes(x = long, y = lat, group = group),
fill = "light grey") +
#create chloropleth layer for countries with data
geom_polygon(data = world4, aes(x = long, y = lat, group = group, fill = interest),
col = "white") +
#add map theme from ggthemes
theme_map() +
#Set the zoom
coord_fixed(xlim = c(-130, 160),
ylim = c(-50, 75), ratio = 1.4) +
#Add city layer - include col in aes() to get city as a separate legend item
geom_point(data = city, aes(x= long, y = lat, col = interest),
shape = 21, inherit.aes = F, size = 3, fill = "yellow") +
#set fill for countries by interest (include city (special) to have the correct number of aesthetics)
scale_fill_manual(name = NULL,
breaks = c("interest", "past", "current", "special"),
values = c(interest = "#a7ef88", past = "#3a7f1d", current = "#1b5104", special = "yellow"),
labels = c("interest", "past", "current", "city")) +
#set color for cities and labels for cities legend
scale_color_manual(name = NULL,
breaks = c("special"),
values = c(special = "black"),
labels = c("cities")) +
#set order of legend items (fill first)
guides(fill = guide_legend(order = 1), color = guide_legend(order = 2)) +
#set legend position and vertical arrangement
theme(legend.text = element_text(size = 9), legend.position = "bottom", legend.box = "vertical")
Gives the following:

Recentering state abbreviation on ggplot2

So I modified the shape profile to add Hawaii and Alaska and so my data frame is using a different long, lat coordinates than the stock state coordinates provided by maps package (map_data("state")) shown below
states <- data.frame(state.center, state.abb)
states
x y state.abb
1 -86.7509 32.5901 AL
2 -127.2500 49.2500 AK
3 -111.6250 34.2192 AZ
4 -92.2992 34.7336 AR
5 -119.7730 36.5341 CA
My data frame have coordinates as follow.
When I plot it using the code below I get a map without any state abbreviation labels.
p <- function(data, brks, title) {
ggp <- ggplot() +
geom_polygon(data = data, aes(x = long, y = lat, group = group,
fill = IMSUB), color = "black", size = 0.15) +
scale_fill_gradient2(limits=c(-1,1), breaks = c(-1, 0, 1), labels=c("Trump", 0, "Clinton"), low = "red", mid = "white",
high = "blue", midpoint = 0, space = "Lab",
na.value = "grey50", guide = "colourbar") +
theme_nothing(legend = TRUE) + labs(title = title, fill = "") +
geom_text(data = states, aes(x = x, y = y, label = state.abb), size = 3)
return(ggp)
}
i feel like I can replace the coordinates in states data frame with one in us50 but I am not sure how to replace them correctly.
Did you try it with the size inside the aes()?
geom_text(data=state, aes(x y, label = state.abb, size=3)
If not, this other method will likely work instead, just replace the geom_text line:
with(states, annotate(geom="text", x = x y=y, label = state.abb, size = 3))
It should apply annotation using states, as text with x & y as your lat and long..That should work.

Resources