Related
I'm trying to make a world map with a custom legend on the right side. The legend should be with the prepared text on the left and the generated numbers on the right. I tried but to no avail. I need help My code is as follows:
library(dplyr)
library(ggplot2)
library(ggrepel)
library(rworldmap)
world_map_without_antarctica <- getMap()[-which(getMap()$ADMIN=='Antarctica'),] #get data from web
world_map_without_antarctica_t <- fortify(world_map_without_antarctica)
Data <- data.frame( "lon"=c(17.816883, 38.544239,20.895352,20.819651,35.392102,99.060241,
43.756911, 10.288485, 16.566191, 14.076159,8.118301,16.596266,
121.544442,-73.077732,14.938152),
"lat"=c(44.1807678, 35.0126143, 42.5793648, 44.2330372, 38.9907297,
39.5015541, 33.0368223, 51.1337227, 45.0162344, 47.6139488,
46.7917377, 62.8114850, 15.7509443, 3.9272139, 46.1254221),
"NAME"=c("Bosnia and Herzegovina", "Syria", "Kosovo","Republic of Serbia",
"Turkey","United States of America","Iraq","Germany","Croatia",
"Austria","Switzerland","Sweden","Philippines","Colombia","Slovenia"),
"Count"=c(65800,32636,15005,9276,6979,6528,6449,
5830,4862,3109,2959,2777,2577,2315,1394))
Data$label <- paste0(Data$NAME,': ',Data$Count)
word_data_merged <- merge(world_map_without_antarctica_t, Data[ , c("NAME","Count")], by.x="id", by.y="NAME", all.x=T)
word_data_merged <- word_data_merged %>% arrange(id, order)
country_shapes <- geom_polygon(data = world_map_without_antarctica_t, aes(x = long, y = lat, group = group),fill = NA)
maptheme <-
theme(panel.grid = element_blank())+
theme(axis.text = element_blank())+
theme(axis.ticks = element_blank())+
theme(axis.title = element_blank())+
theme(legend.position = "bottom")+
theme(panel.grid = element_blank())+
theme(plot.margin = unit(c(0, 0, 0.5, 0), 'cm'))
guide = guide_colorbar(
title="legend_title",
label = TRUE,
draw.ulim = TRUE,
draw.llim = TRUE,
frame.colour = "black",
ticks = TRUE,
nbin = 10,
label.position = "bottom",
barwidth = 13,
barheight = 1.3,
direction = 'horizontal')
ggplot(word_data_merged) +
labs(title = "plot_title", subtitle = "plot_subtitle") +
country_shapes +
scale_fill_gradient(high = "#381802", low = "#fccaa7", guide = guide) +
geom_polygon(aes(long, lat, group = group, fill=Count),alpha=1) +
geom_point(data=Data[Data$label !="",],aes(x = lon, y = lat), shape = 21,fill= "#275083", color = "#275083", size = 1.5,alpha=0.5) +
geom_path(aes(x=long,y=lat, group = group), color="#c7c9c9", size= 0.5, alpha=0.4) +
geom_label_repel(data=Data,aes(x= lon,y= lat,label = label),
size = 5,
show.legend= F,
fontface = "bold",
point.padding = unit(0.2, "lines") ) +
maptheme +
theme(panel.background = element_rect(fill = "#ebf2f7"))
After running the code, the following world map is obtained:
How can I add a legend with free text entry? I would like the map to look like in this picture:
This might help:
a) changing plot.margin,
b) adding geom_text for the annotation (updated with #Tung's suggestion to use check_overlap = TRUE to sharpen up the text), and
c) coord_cartesian(clip = 'off') to allow drawing outside of the plot area
ggplot(word_data_merged) +
labs(title = "plot_title", subtitle = "plot_subtitle") +
country_shapes +
scale_fill_gradient(high = "#381802", low = "#fccaa7", guide = guide) +
geom_polygon(aes(long, lat, group = group, fill=Count),alpha=1) +
geom_point(data=Data[Data$label !="",],aes(x = lon, y = lat), shape = 21,fill= "#275083", color = "#275083", size = 1.5,alpha=0.5) +
geom_path(aes(x=long,y=lat, group = group), color="#c7c9c9", size= 0.5, alpha=0.4) +
geom_label_repel(data=Data,aes(x= lon,y= lat,label = label),
size = 5,
show.legend= F,
fontface = "bold",
point.padding = unit(0.2, "lines") ) +
geom_text(aes(label = "Statistics", x = 180, y = 80),
fontface = "bold",
hjust = -0.5,
size = 5,
check_overlap = TRUE) +
geom_text(aes(label = "Total unique countries = #", x = 180, y = 70),
hjust = -0.35,
size = 3,
check_overlap = TRUE) +
coord_cartesian(clip = 'off')+
maptheme +
theme(panel.background = element_rect(fill = "#ebf2f7"),
plot.margin = unit(c(0, 4, 0.5, 0), 'cm'))
#> Warning: ggrepel: 12 unlabeled data points (too many overlaps). Consider
#> increasing max.overlaps
Based on: ggplot2 - annotate outside of plot
Created on 2021-01-16 by the reprex package (v0.3.0)
I want to generate several plots for diferent categories, so I have the following code:
for (módulo in pruebas) {
plot <- ggplot(data = pruebas.oficiales[pruebas.oficiales$prueba==módulo,],
aes(y = Promedio.prueba, x = año)) +
geom_point(shape = 18, size = 4,
color = "#A32F4A") +
geom_errorbar(data = pruebas.oficiales[pruebas.oficiales$prueba==módulo,],
aes(ymin = Promedio.prueba - Desviacion,
ymax = Promedio.prueba + Desviacion),
color = "#A32F4A", width = 0.4, size = 1.3) +
theme(
panel.background = element_rect(fill = "white",
color = rgb(198, 198, 198,
maxColorValue = 255),
size = 1, linetype = "solid"),
panel.grid.minor = element_line(size = 0.1, linetype = "dashed",
color = rgb(198,198,198, maxColorValue = 255)),
axis.title = element_text(color = "#575756", family = "Montserrat"),
axis.text = element_text(family = "Montserrat")
) + geom_text(aes(label = Promedio.prueba), hjust = "left",
nudge_x = 0.145, show.legend = F, color = "#575756",
size = 4, family = "Montserrat") +
geom_text(aes(label = paste("(", Desviacion, ")")),
show.legend = F, color = "#575756", hjust = "left",
vjust = 2, nudge_x = 0.1, size = 4, family = "Montserrat") +
xlab(NULL) + ylab("Promedio de la prueba")
assign(paste0("plot.", módulo), plot)
}
If the corresponding "prueba" has four categories for the variable "año" I get a plot like
If the corresponding "prueba" has two categories for the variable "año" I get a plot like
For the latter, the upper labels are not align with the lower labels. Does anyone know how I can make all the plots have aligned labels regardless on the number of categories for "año" they have?
I did a graph with ggplot. My aim is to add labels at the top of the vertical lines I put in the graph. The problem is that these labels appear not above enough. They intersect the vertical line. Instead, I would like them not to touch the vertical lines.
For instance:
date <- seq(2000, 2010, by = 1)
value <- seq(1, 11, by=1)
df <- data.frame(Date = date, Value = value)
ggplot(df, aes(x = df$Date)) + geom_line(aes(y = df$Value, colour = "Value"), size = 1) + theme_classic() + theme(axis.line = element_line(colour = "grey", size = 0.8)) + labs(y = "\n \n", x = "", colour = "") + theme(axis.title = element_text(family = "Times New Roman", face = "plain", size = 12, colour = "black")) +
geom_vline(xintercept = df$Date[c(3)], linetype="dashed", colour = "black", size=1) +
geom_text(aes(x=df$Date[3], y= Inf, label = "Label"), colour = "black", vjust = 1, size = 5)
How can I push the label in a way that they don't intersect the dashed lines?
Thanks a lot for your help!
This'll be hard with your current approach because geom_vline draws a line that goes on forever in both directions. You could push your text to the right or left in your call to geom_text though. If you really want to have the text right above the vertical line, I'd suggest using annotate to draw the line instead:
library(ggplot2)
date <- seq(2000, 2010, by = 1)
value <- seq(1, 11, by=1)
df <- data.frame(Date = date, Value = value)
ggplot(df, aes(x = Date)) +
geom_line(aes(y = Value, colour = Value), size = 1) +
theme_classic() + theme(axis.line = element_line(colour = "grey", size = 0.8)) +
labs(y = "\n \n", x = "", colour = "") +
theme(
axis.title = element_text(family = "Times New Roman", face = "plain", size = 12, colour = "black")) +
geom_text(aes(x=df$Date[3], y=max(df$Value), label = "Label"), colour = "black", vjust = 1, size = 5, nudge_y = 1) +
annotate("segment", x=df$Date[3], xend=df$Date[3], y=0, yend=max(df$Value), linetype="dashed", size=1)
Look at the last two lines above: I use nudge_y in the call to geom_text to move the label up and then I use annotate to draw a fixed-length line.
I also made some minor edits to other parts of your code. Notably, you don't have to preface column names with df$ if they're in your aes() calls and the colour argument of aes should always be an unquoted (no ") column name.
Perhaps inserting a geom_segment is what you are looking for:
ggplot(df, aes(x = Date)) +
geom_line(aes(y = Value, colour = "Value"), size = 1) +
geom_segment(aes(x = 2005, y = 0, xend = 2005, yend = 9, colour = "segment"), data = df) +
geom_text(aes(x=df$Date[6], y= 10, label = "Label"), colour = "black", vjust = 1, size = 5)
I would suggest to go with geom_segment. I also made similar edits to your code as amoeba did
ggplot(df, aes(x = Date)) +
geom_line(aes(y = Value, colour = "Value"), size = 1) +
labs(y = "\n \n", x = "", colour = "") +
theme_classic() +
theme(axis.line = element_line(colour = "grey", size = 0.8),
axis.title = element_text(family = "Times New Roman",
face = "plain",
size = 12,
colour = "black")) +
geom_segment(aes(x = df$Date[3],xend=df$Date[3],y=0,yend=max(value*0.97)),
linetype="dashed", colour = "black", size=1) +
geom_text(aes(x=df$Date[3], y= Inf, label = "Label"), colour = "black", vjust = 1, size = 5)+
ylim(0,NA)
Perhaps there are better options out there, but here is one approach.
Add additional margin space above the plot with plot.margin in your theme.
Add coord_cartesian to turn off clipping (allowing drawing outside the extent of the plot panel).
Use annotation_custom to add the text.
library(ggplot2)
date <- seq(2000, 2010, by = 1)
value <- seq(1, 11, by=1)
df <- data.frame(Date = date, Value = value)
ggplot(df, aes(x = Date)) +
geom_line(aes(y = Value, colour = Value), size = 1) +
theme_classic() +
theme(plot.margin = unit(c(2,1,1,1), "cm"), axis.line = element_line(colour = "grey", size = 0.8)) +
labs(y = "\n \n", x = "", colour = "") +
theme(axis.title = element_text(family = "Times New Roman", face = "plain", size = 12, colour = "black")) +
geom_vline(xintercept = df$Date[c(3)], linetype="dashed", colour = "black", size=1) +
annotation_custom(grob = textGrob(label = "Label", hjust = .5, gp = gpar(cex = 1.2)),
ymin = 12, ymax = 12, xmin = df$Date[c(3)], xmax = df$Date[c(3)]) +
coord_cartesian(clip = 'off')
I have the following chart I have built using ggplot + ggplotly.
I am trying to add labels to the red (median) and blue (percentile 90%) vertical lines without luck.
Please advise how should I fix it.
The code I have used:
p1 <- ggplot(users_d_total %>% filter(isSame, D_rank == 2), aes(x = D, fill = as.factor(train_user_id))) +
geom_density(alpha = .3) +
labs(title = paste0("Without Normalization Analysis [K = 2]")) +
scale_fill_discrete(name = "Users") +
scale_x_continuous(breaks = by_two) +
geom_vline(aes(xintercept = median(D)), col = 'red', linetype = 1, size = 1) +
geom_text(aes(x = median(D), y = 1, label = "Median"), hjust = 1, angle = 90, colour= "red") +
geom_vline(aes(xintercept = quantile(D, probs = .9)), col = 'blue', linetype = 1, size = 1) +
geom_text(aes(x = quantile(D, probs = .9), y = 1, label = "90th Percentile"), hjust = 1, angle = 90, colour = "blue") +
theme(axis.text.x = element_text(angle = 90, hjust = 1))
ggplotly(p1)
I want the text to be vertical but using the answer from How to add legend for vertical lines in ggplot? didn't help me.
I'm trying to create a multiple plot with the same x-axis but different y-axes, because I have values for two groups with different ranges. As I want to control the values of the axes (respectively the y-axes shall reach from 2.000.000 to 4.000.000 and from 250.000 to 500.000), I don't get along with facet_grid with scales = "free".
So what I've tried is to create two plots (named "plots.treat" and "plot.control") and combine them with grid.arrange and arrangeGrob. My problem is, that I don't know how to control the exact position of the two plots, so that both y-axes are positioned on one vertical line. So in the example below the second plot's y-axis needs to be positioned a bit more to the right.
Here is the code:
# Load Packages
library(ggplot2)
library(grid)
library(gridExtra)
# Create Data
data.treat <- data.frame(seq(2005.5, 2015.5, 1), rep("SIFI", 11),
c(2230773, 2287162, 2326435, 2553602, 2829325, 3372657, 3512437,
3533884, 3519026, 3566553, 3527153))
colnames(data.treat) <- c("Jahr", "treatment",
"Aggregierte Depositen (in Tausend US$)")
data.control <- data.frame(seq(2005.5, 2015.5, 1), rep("Nicht-SIFI", 11),
c(324582, 345245, 364592, 360006, 363677, 384674, 369007,
343893, 333370, 318409, 313853))
colnames(data.control) <- c("Jahr", "treatment",
"Aggregierte Depositen (in Tausend US$)")
# Create Plot for data.treat
plot.treat <- ggplot() +
geom_line(data = data.treat,
aes(x = `Jahr`,
y = `Aggregierte Depositen (in Tausend US$)`),
size = 1,
linetype = "dashed") +
geom_point(data = data.treat,
aes(x = `Jahr`,
y = `Aggregierte Depositen (in Tausend US$)`),
fill = "white",
size = 2,
shape = 24) +
scale_x_continuous(breaks = seq(2005, 2015.5, 1),
minor_breaks = seq(2005, 2015.5, 0.5),
limits = c(2005, 2015.8),
expand = c(0.01, 0.01)) +
scale_y_continuous(breaks = seq(2000000, 4000000, 500000),
minor_breaks = seq(2000000, 4000000, 250000),
labels = c("2.000.000", "2.500.000", "3.000.000",
"3.500.000", "4.000.000"),
limits = c(2000000, 4000000),
expand = c(0, 0.01)) +
theme(text = element_text(family = "Times"),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
axis.line.x = element_line(color="black", size = 0.6),
axis.line.y = element_line(color="black", size = 0.6),
legend.position = "none") +
geom_segment(aes(x = c(2008.7068),
y = c(2000000),
xend = c(2008.7068),
yend = c(3750000)),
linetype = "dotted") +
annotate(geom = "text", x = 2008.7068, y = 3875000, label = "Lehman\nBrothers + TARP",
colour = "black", size = 3, family = "Times") +
geom_segment(aes(x = c(2010.5507),
y = c(2000000),
xend = c(2010.5507),
yend = c(3750000)),
linetype = "dotted") +
annotate(geom = "text", x = 2010.5507, y = 3875000, label = "Dodd-Frank-\nAct",
colour = "black", size = 3, family = "Times") +
geom_rect(aes(xmin = 2007.6027, xmax = 2009.5, ymin = -Inf, ymax = Inf),
fill="dark grey", alpha = 0.2)
# Create Plot for data.control
plot.control <- ggplot() +
geom_line(data = data.control,
aes(x = `Jahr`,
y = `Aggregierte Depositen (in Tausend US$)`),
size = 1,
linetype = "solid") +
geom_point(data = data.control,
aes(x = `Jahr`,
y = `Aggregierte Depositen (in Tausend US$)`),
fill = "white",
size = 2,
shape = 21) +
scale_x_continuous(breaks = seq(2005, 2015.5, 1), # x-Achse
minor_breaks = seq(2005, 2015.5, 0.5),
limits = c(2005, 2015.8),
expand = c(0.01, 0.01)) +
scale_y_continuous(breaks = seq(250000, 500000, 50000),
minor_breaks = seq(250000, 500000, 25000),
labels = c("250.000", "300.000", "350.000", "400.000",
"450.000", "500.000"),
limits = c(250000, 500000),
expand = c(0, 0.01)) +
theme(text = element_text(family = "Times"),
axis.title.x = element_blank(), # Achse
axis.title.y = element_blank(), # Achse
axis.line.x = element_line(color="black", size = 0.6),
axis.line.y = element_line(color="black", size = 0.6),
legend.position = "none") +
geom_segment(aes(x = c(2008.7068),
y = c(250000),
xend = c(2008.7068),
yend = c(468750)),
linetype = "dotted") +
annotate(geom = "text", x = 2008.7068, y = 484375, label = "Lehman\nBrothers + TARP",
colour = "black", size = 3, family = "Times") +
geom_segment(aes(x = c(2010.5507),
y = c(250000),
xend = c(2010.5507),
yend = c(468750)),
linetype = "dotted") +
annotate(geom = "text", x = 2010.5507, y = 484375, label = "Dodd-Frank-\nAct",
colour = "black", size = 3, family = "Times") +
geom_rect(aes(xmin = 2007.6027, xmax = 2009.5, ymin = -Inf, ymax = Inf),
fill="dark grey", alpha = 0.2)
# Combine both Plots with grid.arrange
grid.arrange(arrangeGrob(plot.treat, plot.control,
ncol = 1,
left = textGrob("Aggregierte Depositen (in Tausend US$)",
rot = 90,
vjust = 1,
gp = gpar(fontfamily = "Times",
size = 12,
colout = "black",
fontface = "bold")),
bottom = textGrob("Jahr",
vjust = 0.1,
hjust = 0.2,
gp = gpar(fontfamily = "Times",
size = 12,
colout = "black",
fontface = "bold"))))
Do:
install.packages("cowplot")
but do not library(cowplot) as it'll mess up your theme work.
Then, do:
grid.arrange(
arrangeGrob(cowplot::plot_grid(plot.treat, plot.control, align = "v", ncol=1),
ncol = 1,
left = textGrob("Aggregierte Depositen (in Tausend US$)",
rot = 90,
vjust = 1,
gp = gpar(fontfamily = "Times",
size = 12,
colout = "black",
fontface = "bold")),
bottom = textGrob("Jahr",
vjust = 0.1,
hjust = 0.2,
gp = gpar(fontfamily = "Times",
size = 12,
colout = "black",
fontface = "bold"))))