Good Morning.
I am trying to plot using a ggplot2 package but facing a problem below:
To make it more understandable, here is the target image that I want to make.
Just like the image, I want to do the followings:
1) Put a text 'median' above the dashed line so that it is ok to see the character clearly.
2) Rotate the degree of triangle (Not ^ ^ but < >) so that it makes sense.
To achieve the above, I've done so far with the codes:
# binding the data, defining the x and y aesthetics, title, labels
w_plot <- ggplot(
data = com_mal,
aes(x = reorder(name, -median_age), y = median_age)
)
labels = c('5 yrs old', 10, 15, 20, 25, 30)
w_plot +
geom_linerange(
aes(ymin = q1_age, ymax = q3_age),
color = "#76bde0",
size = 6,
alpha = 0.7
) +
geom_point(fill = "#ed3324", colour = "white", size = 4, shape = 21) +
geom_text(aes(y = 9, x = 15, label = '25th')) +
geom_text(aes(y = 20, x = 15, label = '75th percentile')) +
geom_text(aes(y = 30, x = 22, label = 'median')) +
geom_point(aes(y = 8.25, x = 15), shape = 17) +
geom_point(aes(y = 21.75, x = 15), shape = 17) +
geom_point(aes(y = 29, x = 21.9), fill = "#ed3324", colour = "white", size = 4, shape = 21) +
geom_hline(aes(yintercept = 5), linetype = 'dotted') +
geom_hline(aes(yintercept = 10), linetype = 'dotted') +
geom_hline(aes(yintercept = 15), linetype = 'dotted') +
geom_hline(aes(yintercept = 20), linetype = 'dotted') +
geom_hline(aes(yintercept = 25), linetype = 'dotted') +
geom_hline(aes(yintercept = 30), linetype = 'dotted') +
scale_y_continuous(breaks = seq(5, 30, by = 5), position = 'right', labels = labels) +
coord_flip() +
labs(title = 'Youngest Male Names',
subtitle = 'By estimated median age for Americans alive as of Jan 1. 2014',
x = NULL, y = NULL, caption = 'SOURCE: SOCIAL SECURITY ADMINISTRATION') +
theme(plot.title = element_text(face = 'bold', size = 16),
panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
axis.ticks = element_blank(), plot.caption = element_text(size = 10))
Thank you very much!
For the triangles, you could use geom_text() instead, setting the family argument to a font that supports the character, and for the label use geom_label():
geom_text(label = "▶", size = 3, family = "HiraKakuPro-W3")
geom_label(aes(y = 4, x = 10, label = 'median'), fill = "grey92", label.size = NA)
label.size removes the outline of the label, and "grey92" is (approximately?) the color of the background.
If you want the dotted line to be behind the label, you should add geom_label() to the plot after the line. (Also notice that you can add all the dotted lines in the same line of code.)
w_plot +
geom_linerange(
aes(ymin = q1_age, ymax = q3_age),
color = "#76bde0",
size = 6,
alpha = 0.7
) +
geom_point(fill = "#ed3324", colour = "white", size = 4, shape = 21) +
geom_text(aes(y = 9, x = 15, label = '25th')) +
geom_text(aes(y = 20, x = 15, label = '75th percentile')) +
geom_text(aes(y = 8.25, x = 15),label = "◀", size = 3,
family = "HiraKakuPro-W3") +
geom_text(aes(y = 21.75, x = 15),label = "▶", size = 3,
family = "HiraKakuPro-W3") +
geom_point(aes(y = 29, x = 21.9), fill = "#ed3324", colour = "white",
size = 4, shape = 21) +
geom_hline(yintercept = seq(5, 30, by = 5), linetype = 'dotted') +
geom_label(aes(y = 30, x = 22, label = 'median'),
fill = "grey92", label.size = NA) +
scale_y_continuous(breaks = seq(5, 30, by = 5),
position = 'right', labels = labels) +
coord_flip() +
labs(title = 'Youngest Male Names',
subtitle = 'By estimated median age for Americans alive as of Jan 1. 2014',
caption = 'SOURCE: SOCIAL SECURITY ADMINISTRATION') +
theme(plot.title = element_text(face = 'bold', size = 16),
panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
axis.ticks = element_blank(), plot.caption = element_text(size = 10))
Related
What is this type of data visualization plot called and how do I recreate it in R?
Image Source: https://www.pewresearch.org/global/2020/04/30/worldwide-optimism-about-future-of-gender-equality-even-as-many-see-advantages-for-men/pg_2020-04-30_global-gender-equality_0-02/
My Google search only resulted in regular bubble plots like this: https://r-graph-gallery.com/320-the-basis-of-bubble-plot.html
Something like this?
df <- data.frame(Question = rep(c("Getting\nhigh-paying jobs",
"Being leaders in\ntheir community",
"Expressing their\npolitical views",
"Getting a good\neducation"), 3),
Answer = rep(c("Men have more\nopportunities",
"Women have more\nopportunities",
"Both about\nthe same"), each = 4),
Value = c(54, 44, 31, 11, 3, 4, 3, 6, 38, 49, 63, 81))
library(ggplot2)
ggplot(df, aes(y = factor(Question, rev(unique(Question))),
x = factor(Answer, unique(Answer)),
fill = factor(Answer, unique(Answer)))) +
geom_point(shape = 21, aes(size = Value, color = after_scale(fill))) +
geom_text(aes(label = Value, color = Answer)) +
annotate("segment", x = rep(-Inf, 3), xend = rep(Inf, 3),
y = 1:3 + 0.5, yend = 1:3 + 0.5, linetype = 2, alpha = 0.5) +
scale_y_discrete() +
scale_x_discrete(position = "top") +
scale_size_continuous(range = c(5, 30)) +
scale_fill_manual(values = c("#959e4a", "#0f6599", "#dddac8")) +
scale_color_manual(values = c("black", "white", "white")) +
ggtitle(paste("Many think men have more opportunities than women",
"when it comes to getting high-paid jobs", sep = "\n")) +
theme_void() +
theme(legend.position = "none",
axis.text.x = element_text(face = 2),
axis.text.y = element_text(hjust = 1, face = 2),
plot.margin = margin(30, 30, 30, 30),
plot.title = element_text(size = 16, face = 2, family = "serif",
margin = margin(20, 0, 50, 0)))
Here's an example. Lots more formatting tweaks could be done, but I'd think of this fundamentally as a geom_point and a geom_text layer, the rest is tidying up.
library(ggplot2)
fake_data <- data.frame(x = rep(LETTERS[1:3], each = 4),
y = letters[1:4],
val = (1:12) / 12)
ggplot(fake_data, aes(x=1, y = 1, label = scales::percent(val))) +
geom_point(aes(size = val, color = x), alpha = 0.3) +
geom_text() +
scale_size_area(max_size = 20) +
guides(size = "none", color = "none") +
facet_grid(y ~ x, switch = "y") +
theme_void() +
theme(strip.text = element_text())
I have some batch test data which was performed under different mixing conditions.
While I have managed to group the data, I am not sure how to define different aethitics for the geom_smooth lines.
M3<- ggplot(subset(VFA2, VFA %in% "HPr"), aes(x = Time, y = value, group = mix, shape = Test, colour = Test))+geom_point(size = 6, colour = "purple4")+
labs(x = "Anaerobic Time (h)\n Continuous Mixing", y = "HPr Concentration\n(mg HPr/L)")+theme(panel.background = element_rect(fill = "White", colour = "grey"),panel.grid.major = element_line(color = 'grey'), legend.position="bottom", text= element_text(size = 28, family = "Arial"))+
scale_x_discrete(breaks = factor(VFA2$Time), expand = c(-0.25,2))+scale_y_continuous(limits = c(-0.25, 60),breaks = c(0, 10,20, 30, 40, 50, 60))+[![enter image description here][1]][1] scale_shape_manual(values = c(0,1,2,5,7,13,14,9))
M3<- M3 + geom_smooth(method= "gam", formula = y~poly(x,4), se = F, colour = "black", linetype = "dashed")
Is this what you are looking for :
M3<- ggplot(subset(VFA2, VFA %in% "HPr"), aes(x = Time, y = value, group = mix, shape = Test))+
geom_point(size = 6, colour = "purple4")+
geom_smooth(aes(colour=mix), method= "gam", formula = y~poly(x,4), se = F, linetype = "dashed")+
labs(x = "Anaerobic Time (h)\n Continuous Mixing", y = "HPr Concentration\n(mg HPr/L)")+
theme(panel.background = element_rect(fill = "White", colour = "grey"),panel.grid.major = element_line(color = 'grey'), legend.position="bottom", text= element_text(size = 28, family = "Arial"))+
scale_x_discrete(breaks = factor(VFA2$Time), expand = c(-0.25,2))+
scale_y_continuous(limits = c(-0.25, 60),breaks = c(0, 10,20, 30, 40, 50, 60))+
scale_shape_manual(values = c(0,1,2,5,7,13,14,9))+
scale_color_manual(values = c("black", "red"))
I am trying to change the legend items of this plot.
My code is:
library(ggplot2)
library(HDInterval)
library(ggridges)
df <- data.frame(
density = c(rgamma(400, 2, 10), rgamma(400, 2.25, 9), rgamma(400, 5, 7)),
source = rep(c("source_1", "source_2", "source_3"),
each = 400))
ggplot(df, aes(x = density, color = source, linetype = source,
fill = after_stat(ifelse(quantile == 2, NA, color)))) +
geom_density_ridges_gradient(aes(y = 0), quantile_lines = TRUE, size=1.2,
quantile_fun = hdi, # vline_linetype = 0, scale = 1) +
labs(y = "Density", x = "Contribution") +
scale_linetype_cyclical(name = "Source", values = c("solid", "dotted", "longdash"),
labels = c("source1", "source2", "source3"),
guide = "legend") +
scale_fill_cyclical(name = "Source", values = c("#31a354", "#2c7fb8", "#d95f0e"),
labels = c("source1", "source2", "source3"),
guide = "none", na.value = "transparent") +
scale_color_cyclical(name = "Source", values = c("#31a354", "#2c7fb8", "#d95f0e"),
labels = c("source1", "source2", "source3"),
guide = "none") +
ylim(0, 8) + xlim(0, 1) +
theme(#legend.position=c(.85,.75),
legend.text = element_text(size=16), # item legend text font size
legend.title=element_text(size=18), # title font size
legend.key.height= unit(1, 'cm'),# box height
legend.key.width= unit(1, 'cm')) + # box width
guides(color = guide_legend(override.aes = list(fill = "white")))+
theme(axis.text.y = element_text(size = 12, vjust = 0.5),
axis.text.x = element_text(size = 12, vjust = 0.5),
axis.title.x = element_text(size = 14),
axis.title.y = element_text(size = 14))
I would like to show lines in the legend, instead of the boxes.
I would appreciate your help.
I have tried to understand ggridges deeply, however it is a bit different or rigid for some things.
Thanks in advance.
ggplot(df, aes(x = density, color = source, linetype = source,
fill = after_stat(ifelse(quantile == 2, NA, color)))) +
geom_density_ridges_gradient(aes(y = 0), size=1.2,
quantile_lines = TRUE, quantile_fun = hdi,
key_glyph = "path") +
...
https://ggplot2.tidyverse.org/reference/draw_key.html
Background
I took the data from a Stephen Few Example and wanted to add labels to each of the bars to pull the legend from the side of the graphic.
The code in the "Hack Graphic" section got me there because I couldn't get the position_dodge() to work with the text labels.
Load Data
library(tidyverse)
library(forcats)
### Build data from his table
candidates <- tibble::tibble(`Rating Areas` = c("Experience",
"Communication", "Friendliness", "Subject matter knowledge", "Presentation",
"Education"), `Karen Fortou` = c(4,3.5, 4, 4, 3, 3.5), `Mike Rafun` = c(4.5,
2, 2, 5, 1.5, 4.5), `Jack Nymbul` = c(2.5, 5, 4.5, 2.5, 2.75, 2)) %>%
gather("Candidates", "Score", -`Rating Areas`)
# The totals for each candidate
totals <- candidates %>% group_by(Candidates) %>% summarise(Score =
sum(Score))
Hack Graphic
Notice how I used manually created x-axis values (x = c(seq(.6,1.35, by = .15), seq(1.6,2.35, by = .15), seq(2.6,3.35, by = .15))) to place the labels instead of using position = position_dodge() as described in this post.
candidates %>%
ggplot(aes(x = fct_reorder(Candidates, Score), y = Score)) +
geom_col(data = totals, alpha = .45) +
geom_col(aes(fill = `Rating Areas`), position = position_dodge(.9), color = "black",
show.legend = FALSE) +
geom_text(label = rep(c("Experience", "Communication", "Friendliness",
"Subject matter knowledge", "Presentation", "Education"),3),
x = c(seq(.6,1.35, by = .15), seq(1.6,2.35, by = .15),
seq(2.6,3.35, by = .15)), y = 5.1, angle = 90, color = "black",
hjust = "left", size = 4, fontface = "bold") +
scale_fill_brewer(type = "qual") +
scale_y_continuous(breaks = seq(0, 25, by = 2)) +
theme_bw() +
labs(x = "\nCandidates", y = "Rating Score") +
theme(axis.text.x = element_text(size = 14, color = "black"), legend.text = element_text(size = 14),
legend.title = element_text(size = 15), axis.title = element_text(size = 15))
Graphic Code that doesn't work
When I follow the example from the previous Stack answer using geom_text(aes(label =Rating Areas), position = position_dodge(width = 0.9), angle = 90, color = "black", hjust = "left", size = 4, fontface = "bold") it does not spread the labels out ever each bar.
I must be missing something obvious. Please help with how to get position_dodge() to work with this example?
candidates %>%
ggplot(aes(x = fct_reorder(Candidates, Score), y = Score)) +
geom_col(data = totals, alpha = .45) +
geom_col(aes(fill = `Rating Areas`), position = position_dodge(.9), color = "black", show.legend = FALSE) +
geom_text(aes(label = `Rating Areas`), position = position_dodge(width = 0.9), angle = 90, color = "black", hjust = "left", size = 4, fontface = "bold") +
scale_fill_brewer(type = "qual") +
scale_y_continuous(breaks = seq(0, 25, by = 2)) +
theme_bw() +
labs(x = "\nCandidates", y = "Rating Score") +
theme(axis.text.x = element_text(size = 14, color = "black"), legend.text = element_text(size = 14), legend.title = element_text(size = 15), axis.title = element_text(size = 15))
I think you need to have the same mapping for both geom_col and geom_text. You can add fill = Rating Areas to the aesthetics of geom_text. You will get a warning though.
candidates %>%
ggplot(aes(x = fct_reorder(Candidates, Score), y = Score)) +
geom_col(data = totals, alpha = .45) +
geom_col(aes(fill = `Rating Areas`), position = position_dodge(.9), color = "black", show.legend = FALSE) +
geom_text(aes(fill = `Rating Areas`, label = `Rating Areas`), position = position_dodge(width = 0.9), angle = 90, color = "black", hjust = "left", size = 4, fontface = "bold") +
scale_fill_brewer(type = "qual") +
scale_y_continuous(breaks = seq(0, 25, by = 2)) +
theme_bw() +
labs(x = "\nCandidates", y = "Rating Score") +
theme(axis.text.x = element_text(size = 14, color = "black"), legend.text = element_text(size = 14), legend.title = element_text(size = 15), axis.title = element_text(size = 15))
Edit: Here's a way to do it without the warning:
candidates %>%
ggplot(aes(x = fct_reorder(Candidates, Score), y = Score, fill = `Rating Areas`)) +
geom_col(data = totals, aes(x = fct_reorder(Candidates, Score), y = Score), alpha = .45, inherit.aes = FALSE) +
geom_col(position = position_dodge(.9), color = "black", show.legend = FALSE) +
geom_text(aes(label = `Rating Areas`), position = position_dodge(width = 0.9), angle = 90, color = "black", hjust = "left", size = 4, fontface = "bold") +
scale_fill_brewer(type = "qual") +
scale_y_continuous(breaks = seq(0, 25, by = 2)) +
theme_bw() +
labs(x = "\nCandidates", y = "Rating Score") +
theme(axis.text.x = element_text(size = 14, color = "black"), legend.text = element_text(size = 14), legend.title = element_text(size = 15), axis.title = element_text(size = 15))
I am plotting the following data into a ggplot bar chart.
structure(list(MEDIATYPE = c("BACKLIT TOWER", "BILLBOARDS", "BRIDGE PANEL",
"BUILDING FACADES", "BUS SHELTER", "CANTILIVERS", "CYCLE SHELTER",
"FOB", "FREE STANDING PANEL", "GANTRIES"), RENTAL = c(197, 278363,
1423, 26, 35960, 6194, 70, 4845, 27, 9420)), .Names = c("MEDIATYPE",
"RENTAL"), row.names = c(NA, 10L), class = "data.frame")
I am using the following code to render the chart. It is working fine. However the problem is the yaxis values keeps changing and the annotation at the top of the chart sometimes disappears or in other instances appears in the middle of the chart.
library(ggplot2)
library(stringr) # str_wrap
ggplot(b, aes(x=reorder(MEDIATYPE,-RENTAL), y=RENTAL, fill=MEDIATYPE)) + geom_bar(stat = "identity", width = 0.8) +
theme(legend.position = "none") + xlab("MEDIATYPE") + ylab("SPENDS") +
scale_x_discrete(labels = function(x) str_wrap(x, width = 1)) +
theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
geom_text(aes(label=RENTAL), vjust = 0.5,hjust = 1, angle = 90, colour = "white",size = 3) +
ggtitle("MEDIAWISE SPENDS") +
theme(plot.title=element_text(size=rel(1.4), lineheight = 1, face = "bold")) +
theme(axis.text = element_text(size = 8, color = "black")) +
theme(axis.title = element_text(size=10, face = "bold")) +
theme(panel.background = element_rect(fill = "grey95")) +
ggplot2::annotate(geom = "text", label = "Source:ABC Monitors", x = Inf, y = -Inf, color = "blue",size = 3,fontface = "italic",hjust = 1, vjust = -30)
Is it possible to dynamically set the position of the annotation?
Extending #user20650's idea, textGrob allows the use relative coordinates, but use annotation_custom to restrict the grob to the plot panel.
b = structure(list(MEDIATYPE = c("BACKLIT TOWER", "BILLBOARDS", "BRIDGE PANEL",
"BUILDING FACADES", "BUS SHELTER", "CANTILIVERS", "CYCLE SHELTER",
"FOB", "FREE STANDING PANEL", "GANTRIES"), RENTAL = c(197, 278363,
1423, 26, 35960, 6194, 70, 4845, 27, 9420)), .Names = c("MEDIATYPE",
"RENTAL"), row.names = c(NA, 10L), class = "data.frame")
# Try a different y range
# b[2, 2] = 30000
library(ggplot2)
library(stringr) # str_wrap
library(grid)
label = textGrob(label = "Source:ABC Monitors", x = .95, y = 0.95,
just = c("right", "top"),
gp=gpar(fontface = "italic", col = "blue",size = 3))
p = ggplot(b, aes(x=reorder(MEDIATYPE,-RENTAL), y=RENTAL, fill=MEDIATYPE)) + geom_bar(stat = "identity", width = 0.8) +
theme(legend.position = "none") + xlab("MEDIATYPE") + ylab("SPENDS") +
scale_x_discrete(labels = function(x) str_wrap(x, width = 1)) +
theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
geom_text(aes(label=RENTAL), vjust = 0.5,hjust = 1, angle = 90, colour = "white",size = 3) +
ggtitle("MEDIAWISE SPENDS") +
theme(plot.title=element_text(size=rel(1.4), lineheight = 1, face = "bold")) +
theme(axis.text = element_text(size = 8, color = "black")) +
theme(axis.title = element_text(size=10, face = "bold")) +
theme(panel.background = element_rect(fill = "grey95")) +
annotation_custom(label, xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf)
Instead of adjusting the position using hjust and vjust why not set the y-position to the tallest bar?
ggplot(b, aes(x=reorder(MEDIATYPE,-RENTAL), y=RENTAL, fill=MEDIATYPE)) + geom_bar(stat = "identity", width = 0.8) +
theme(legend.position = "none") + xlab("MEDIATYPE") + ylab("SPENDS") +
scale_x_discrete(labels = function(x) str_wrap(x, width = 1)) +
theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
geom_text(aes(label=RENTAL), vjust = 0.5,hjust = 1, angle = 90, colour = "white",size = 3) +
ggtitle("MEDIAWISE SPENDS") +
theme(plot.title=element_text(size=rel(1.4), lineheight = 1, face = "bold")) +
theme(axis.text = element_text(size = 8, color = "black")) +
theme(axis.title = element_text(size=10, face = "bold")) +
theme(panel.background = element_rect(fill = "grey95")) +
ggplot2::annotate(geom = "text", label = "Source:ABC Monitors",
x = Inf, y = max(b$RENTAL),
color = "blue",size = 3,fontface = "italic",hjust = 1, vjust = 1)