Aligning numbered points on map ggplot - r

I'm trying to align each bcr_code to their respective polygons, however, the numbers come out of place. How do I get the right alignment, preferably in the middle?
here's the code:
library(tidyverse)
library(broom)
library(rgdal)
file1 <- "bcr.gpkg"
if (!file.exists(file.path("data/data/", file1))) {
download.file(paste0("https://raw.githubusercontent.com/lime-n/data/main/", file1),
file.path("data/data/", file1), mode = "wb")
}
p <- readOGR(dsn = "bcr.gpkg")
tidy_bcr <- tidy(p)
ggplot(p, aes(x = long, y = lat, group = group)) +
geom_polygon(color = "black", size = 0.1, fill = "lightgrey") +
coord_equal() +
theme_minimal()
p$id <- row.names(p)
tidy_bcr <- left_join(tidy_bcr, p#data)
bcrcop <- data.frame(bcr_name = sort(p#data$bcr_name),
bcr_code = c(28,17,12,24,19,22,13,26,30,21,31,29,23,11,18,27,25))
tidy_bcr <- left_join(tidy_bcr, bcrcop)
bcrLabel <- tidy_bcr %>%
group_by(bcr_name) %>%
summarise(label_long = mean(range(long)), label_lat = mean(range(lat)), bcr_code = mean(bcr_code))
map <- ggplot(tidy_bcr, aes(x = long, y = lat, group = group, fill = bcr_name)) +
geom_polygon(color = "black", size = 0.1) +
coord_equal() +
theme_void() +
theme(plot.title = element_text(margin = margin(t = 40, b = -40)))
map + geom_text(data = bcrLabel, mapping = aes(x=label_long, y = label_lat, label = bcr_code, group = NA), cex = 4, col = "white")
And the output:
Although, is there also a way to get these codes on the legend, something like:
28: Appalachian Mountains

Try using the sf package for the data and ggsflabel for the labels.
A minimal examle:
library(sf)
library(ggsflabel)
my_data <- read_sf('https://raw.githubusercontent.com/lime-n/data/main//bcr.gpkg') ## Replace with your path to the data
ggplot() +
geom_sf(data = my_data,
aes(fill = bcr_name)) +
geom_sf_label(data = my_data, aes(label = bcr_code))
Change the legend names in the legend using unite on the data first.
my_data <- my_data %>%
unite('new_col', bcr_code, bcr_name, sep = ': ', remove = F)
ggplot() +
geom_sf(data = my_data2,
aes(fill = new_col)) +
geom_sf_label(data = my_data2,
aes(label = bcr_code))
Created on 2020-12-26 by the reprex package (v0.3.0)

Related

Swap key and label in ggplot legend

I have a plot like this:
library("ggplot2")
library("ggtext")
df = data.frame(x = rnorm(n=12), y = rnorm(n=12),
groupshape = rep(c("a","b","c"), 4),
groupcol = rep(c("e","d","f"), 4))
p = ggplot(df, aes(x = x,y = y,
shape = groupshape,
color = groupcol)) +
geom_point() + theme_classic() + labs(shape = "shape", color = "color")
Producing a plot like this:
But I want to know how to get something like this with the legend:
How would I do that? I can get rid of the shape itself through guides by turning them all while, but then the text just hovers menacingly without alignment to the legend below.
This could be achieved via the label.position and the label.theme arguments of guide_legend:
library("ggplot2")
library("ggtext")
df = data.frame(x = rnorm(n=12), y = rnorm(n=12),
groupshape = rep(c("a","b","c"), 4),
groupcol = rep(c("e","d","f"), 4))
ggplot(df, aes(x = x,y = y,
shape = groupshape,
color = groupcol)) +
geom_point() + theme_classic() + labs(shape = "shape", color = "color") +
guides(color = guide_legend(label.position = "left", label.theme = element_text(face = "bold")),
shape = guide_legend(label.position = "left"))

How to fix legend order using ggplot in R?

I am creating a plot that has 2 legends using both ggplot2 and ggnewscale. What I'm trying to achieve is to fix the order of the separate legends so they always appear in the same order. The images and code below show a basic example of the issue I'm having.
First, create some data and set the colour palettes:
df <- data.frame(x = c(1:5), y = runif(10))
df_1 <- data.frame(x = c(1:5), y = runif(10))
pal_1 = rev(colorspace::sequential_hcl(palette = "Blues 3", n = 10))
pal_2 = rev(colorspace::sequential_hcl(palette = "Reds 3", n = 10))
Now create a plot (note the limits I set are between 0 and 1 for the legends):
library(ggplot2)
library(ggnewscale)
ggplot(df, mapping = aes(x, y)) +
geom_point(size = 3, aes(fill = y)) +
scale_fill_gradientn(colors = pal_1, limits = c(0,1), name = "val1") +
new_scale_fill() +
geom_point(data = df_1, size = 3, aes(fill = y)) +
scale_fill_gradientn(colors = pal_2, limits = c(0,1), name = "val2")
This will result in the following image (note that the legend for val1 is on the top):
Now, if we change the limits for val2 to something larger, like so:
ggplot(df, mapping = aes(x, y)) +
geom_point(size = 3, aes(fill = y)) +
scale_fill_gradientn(colors = pal_1, limits = c(0,1), name = "val1") +
new_scale_fill() +
geom_point(data = df_1, size = 3, aes(fill = y)) +
scale_fill_gradientn(colors = pal_2, limits = c(0,10), name = "val2")
We will get this (note that val2 legend is now on top:
It seems that ggplot will put the legend with the larger limit range on the top. I was wonder if there was a way to fix the legend order so that, say val1 is always on the top... no matter the range of the limits?
You could specify the order of the legends via the order argument of guide_xxx:
df <- data.frame(x = c(1:5), y = runif(10))
df_1 <- data.frame(x = c(1:5), y = runif(10))
pal_1 = rev(colorspace::sequential_hcl(palette = "Blues 3", n = 10))
pal_2 = rev(colorspace::sequential_hcl(palette = "Reds 3", n = 10))
library(ggplot2)
library(ggnewscale)
ggplot(df, mapping = aes(x, y)) +
geom_point(size = 3, aes(fill = y)) +
scale_fill_gradientn(colors = pal_1, limits = c(0,1), name = "val1",
guide = guide_colorbar(order = 1)) +
new_scale_fill() +
geom_point(data = df_1, size = 3, aes(fill = y)) +
scale_fill_gradientn(colors = pal_2, limits = c(0,10), name = "val2",
guide = guide_colorbar(order = 2))

Change the representation of the graph

i would like to have help with my graph. I would like to be able to change the graph representation algorithm (LGL or other) but I can't. How can I do it? have tried several options that do not work...
library(NetworkToolbox)
library(dplyr)
library(igraph)
library(ggplot2)
library(ggnetwork)
M1 <- as_tibble(replicate(21,sample(1:3,100,rep=TRUE)))
colnames(M1) <- c("1st", "2nd", "3th", "4th", "5th", "6th","7th","8th","9th","10th",
"11th","12th","13th","14th","15th","16th","17th","18th","19th",
"20th","21th")
M2 <- as.matrix(round(cor(M1[,],method ="kendall"),2))
gr4ph <- graph.adjacency(M2, mode = "undirected",weight=TRUE)
MAST <- MaST(M2, normal = False)
gr4ph <- graph.adjacency(MAST , mode = "lower",weight=TRUE)
ggplot(gr4ph, aes(x = x, y = y, xend = xend, yend = yend)) +
geom_edges(color = "grey", alpha = 1) +
geom_nodes(aes(color = name)) + theme_blank() +
geom_nodetext(aes(label = name), color = "black") +
geom_edgetext(aes(label = weight))+
theme(legend.position = "none")
You can use two solution. The layout argument is the key of the graph's representation :
The following exemple are coded with "Large graph layout"
With ggplot :
ggplot(gr4ph1, aes(x = x, y = y, xend = xend, yend = yend),layout = layout_with_lgl(gr4ph1))+
geom_edges(color = "grey", alpha = 1,size=1.5,) +
geom_nodes(aes(color = name), size = 3) + theme_blank() +
geom_nodetext(aes(label = name), color = "black", size = 3) +
geom_edgetext(aes(label = weight), size = 3,label.padding=unit(0.01, "lines"))+
theme(legend.position = "none")
With ggraph :
ggraph(gr4ph, layout = "lgl") +
geom_edge_link(aes(label = weight), angle_calc = 'along',label_dodge = unit(2.5, 'mm')) +
geom_node_point(aes(size=3,color= name)) +
theme(legend.position = "none")+
geom_node_text(aes(label = name), repel = TRUE)

How do I add a legend using aes, ggplot2 and maps?

I'm trying to make a map with points plotted for the Canadian prairie provinces, but I'm having no luck adding in a legend to my map. I'm very new to mapping in r, so I'm not understanding how I should include aes to get a legend. My data for siteDataTrees is from an excel csv file and the top looks like this:
siteDataTrees
and the data for siteDataBoth is also from a csv file and the top looks like this:
siteDataBoth.
Here's what I have so far for my code:
library(maps)
library(ggplot2)
library(sf)
prairies1 <- map("worldHires","Canada", xlim = c(-120,-87), ylim = c(49,61),
plot = FALSE, fill = TRUE)
prairies <- st_as_sf(prairies1)
ggplot(data = prairies) +
geom_sf() +
geom_point(data = siteDataTrees, aes(x = long, y = lat), size = 2.5, pch = 21,
fill = "purple", show.legend = TRUE) +
geom_point(data = siteDataBoth, aes(x = long, y = lat), size = 2.5, pch = 21,
fill = "light green", show.legend = TRUE) +
geom_text(data = locations, aes(x = long, y = lat, label = name),
size = 2, col = "black", check_overlap = FALSE) +
annotation_scale(location = "tr", width_hint = 0.2) +
ggtitle("Climate Stations and Tree Chronology Locations for South AB") +
labs(x = "latitude", y = "longitude") +
theme(legend.position = "right") +
coord_sf(xlim = c(-115, -110), ylim = c(48.9, 50.49), expand = FALSE)
I've also included a map to show what it looks like without the legend.
How should I take the data frame prairies and use it with aes to include a legend? Is there another way to add in a legend in ggplot2 without using the aes function? Thank you in advance for your help and please let me know if something is missing as this is my first posting
Let me give you a couple of examples on how to work out a legend using a slightly modified example from r-spatial.
First we prepare the data:
library(maps)
library(ggplot2)
library(sf)
library(rnaturalearth)
library(rnaturalearthdata)
world <- ne_countries(scale = "medium", returnclass = "sf")
(sites <- data.frame(longitude = c(-80.144005, -80.109),
latitude = c(26.479005,26.83),
type = c("tree", "station")))
Now we plot. Case 1: color is not an issue
ggplot(data = world) +
geom_sf() +
geom_point(data = sites,
aes(x = longitude, y = latitude, fill = type),
size = 4,
shape = 23) +
coord_sf(xlim = c(-88, -78), ylim = c(24.5, 33), expand = FALSE) +
theme(legend.position = "bottom")
Case 2: fill color is an issue.
Here we can use a named vectors to pass the colors and the labels we want by type of point. For example:
mapfill <- c('tree' = "forestgreen", 'station' = "purple")
maplab <- c('tree' = "trees in prairies", 'station' = "Stations in prairies")
Then we plot combining both mapfill and maplab:
ggplot(data = world) +
geom_sf() +
geom_point(data = sites, aes(x = longitude, y = latitude, fill = type), size = 4,
shape = 23) +
scale_fill_manual(values = mapfill, labels = maplab) +
coord_sf(xlim = c(-88, -78), ylim = c(24.5, 33), expand = FALSE) +
theme(legend.position = "bottom")
Remark 1 If you do not want type in the legend title you can either delete it using legend. title = element_blank() within theme
Remark 2 If, instead of fill, you are using color, use function scale_color_manual. If you are combining both fill and color do the same with scale_***_manual
In spirit of full disclosure, if you do not mind the colors and you want a quick fix (and I cannot stress this enough) you can also code fill = "TextYouWantInLegend" within aes. See following example:
ggplot(data = world) +
geom_sf() +
geom_point(data = sites[1,], aes(x = longitude, y = latitude, fill = "toto"), size = 4,
shape = 23) +
geom_point(data = sites[2,], aes(x = longitude, y = latitude, fill = "koko"), size = 4,
shape = 23) +
coord_sf(xlim = c(-88, -78), ylim = c(24.5, 33), expand = FALSE) +
theme(legend.position = "bottom")

Remove Antarctica from gglpot2 map

I'm trying to reproduce this tutorial on how to plot a scatterplot-like map. Below is the full code and the output:
library(readr)
library(dplyr)
library(DT)
datatable(rladies, rownames = FALSE,
options = list(pageLength = 5))
url_csv <- 'https://raw.githubusercontent.com/d4tagirl/R-Ladies-growth-maps/master/rladies.csv'
rladies <- read_csv(url(url_csv)) %>%
select(-1)
library(ggplot2)
library(maps)
library(ggthemes)
world <- ggplot() +
borders("world", colour = "gray85", fill = "gray80") +
theme_map()
map <- world +
geom_point(aes(x = lon, y = lat, size = followers),
data = rladies,
colour = 'purple', alpha = .5) +
scale_size_continuous(range = c(1, 8),
breaks = c(250, 500, 750, 1000)) +
labs(size = 'Followers')
I want to remove Antartica from the map so that it doesn't take so much empty space. I tried to follow the solution from another similar Stackoverflow question as follows:
world <- map_data("world") %>%
filter(region != "Antarctica") %>%
ggplot(aes(long, lat, group = paste(region, group))) +
geom_polygon() +
coord_fixed()
map <- world +
geom_point(aes(x = lon, y = lat, size = followers),
data = rladies,
colour = 'purple', alpha = .5) +
scale_size_continuous(range = c(1, 8),
breaks = c(250, 500, 750, 1000)) +
labs(size = 'Followers')
But when I try to display the map I get the following error:
Error in paste(region, group) : object 'region' not found
Is there any other way to remove Antartica?
UPDATE: Failed subset attempt
countries <- map_data("world")
map_df <- subset(countries, region != "Antarctica")
map_base <- ggplot(data = map_df, mapping = aes(x = long, y = lat, group = group)) + coord_fixed(1.3) + geom_polygon(color = "black", fill = "gray")
# The base map is created successfully but I cannot plot points on it
map_base + geom_point(aes(x = lon, y = lat, size = followers), data = rladies, colour = 'purple', alpha = .5)
Error:
Error in eval(expr, envir, enclos) : object 'group' not found
Following on hrbmstr's advice, here is a solution using a proper projection and the sf package (with geom_sf from the development version of ggplot2). Note we use coord_sf to set the limits.
library(sf)
world <- map_data("world")
world.sf <- sf::st_as_sf(world, coords = c("long", "lat"), crs = 4326) %>%
group_by(group) %>%
summarize(do_union = FALSE) %>%
st_cast("POLYGON") %>%
ungroup()
world <- ggplot() +
geom_sf(data = world.sf, colour = "gray85", fill = "gray80") +
coord_sf(ylim = c(-50, 90), datum = NA) +
theme(panel.background = element_rect(fill = 'white'))
world +
geom_point(aes(x = lon, y = lat, size = followers),
data = rladies,
colour = 'purple', alpha = .5) +
scale_size_continuous(range = c(1, 8),
breaks = c(250, 500, 750, 1000)) +
labs(size = 'Followers', x = NULL, y = NULL)
We can also use coord_cartesian(ylim = c(-50, 90)) to set the y limits.
library(ggplot2)
library(maps)
library(ggthemes)
world <- ggplot() +
borders("world", colour = "gray85", fill = "gray80") +
theme_map() +
coord_cartesian(ylim = c(-50, 90))
map <- world +
geom_point(aes(x = lon, y = lat, size = followers),
data = rladies,
colour = 'purple', alpha = .5) +
scale_size_continuous(range = c(1, 8),
breaks = c(250, 500, 750, 1000)) +
labs(size = 'Followers')
map

Resources