wrapping the labels of legend in ggplot ZINB model - r

I need help in wrapping the labels of legend in ggplot. I tried various option including
str_wrap(model, width=20)
scale_colour_discrete(labels = function(x) str_wrap(x, width = 5))
guides(colour = guide_legend(nrow = 2))
but without any success
library(ggplot2)
ggplot(coefs, aes(x = estimate, y = term, colour = model)) +
geom_vline(xintercept = 1, lty = 1, color = "yellow", size = 1) +
geom_pointrange(aes(xmin = conf.low, xmax = conf.high),
position = position_dodge(width = 0.5)
) +
facet_wrap(~type, scale = "free") +
geom_text(aes(x = estimate, label = sprintf("%0.2f", estimate)), position = position_dodge(0.5), vjust = -0.5) +
labs(x = "gy", y = "age") +
scale_color_manual(
name = "Model",
labels = c("Fullfasdfasdfad-asdkljaflsdjfals;jfasdf", "Subadfasdfaasdfasdfasdfsdfasdfasf"),
values = c("dodgerblue4", "firebrick4")
)
Data
coefs <- structure(list(model = c(
"all_adj", "all_adj", "all_adj", "all_adj",
"adj_sub", "adj_sub"
), term = c(
"ageb", "agec", "ageb", "agec",
"ageb", "ageb"
), type = c(
"count", "count", "zero", "zero", "count",
"zero"
), estimate = c(
0.937781183281121, 1.09774595782208, 0.895560088459192,
0.891707940838411, 0.76445315191301, 1.01406754426526
), conf.low = c(
0.422176961883128,
0.319479297647212, 0.273199977915238, 0.132809852827134, 0.175087960312586,
0.186498610242251
), conf.high = c(
2.08309222699744, 3.77190696483063,
2.93568058885374, 5.98707878088866, 3.33768592898348, 5.51389087026671
)), row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame"))

Related

Display the basic summary statistics next to the ggplot2 boxplot

Is it possible to display the summary statistics next to the boxplot like:
throu<-structure(list(case_id = c("WC4132791", "WC4130879", "WC4128064",
"WC4121569", "WC4121568", "WC4130112", "WC4131829", "WC4130841",
"WC4130306", "WC4130417", "WC4124741", "WC4130114", "WC4131990",
"WC4121986", "WC4128062", "WC4122478", "WC4130337", "WC4125822",
"WC4127231", "WC4124761", "WC4129398", "WC4131040", "WC4123072",
"WC4131822", "WC4120712", "WC4121978", "WC4130110", "WC4123522",
"WC4130307", "WC4122643", "WC4130383", "WC4122248", "WC4122299",
"WC4122727", "WC4126769", "WC4131186", "WC4125978", "WC4129089",
"WC4121339", "WC4126469", "WC4131800", "WC4125572", "WC4132378",
"WC4123345", "WC4130314", "WC4127722", "WC4129978", "WC4131838",
"WC4130812", "WC4126953"), throughput_time = c(134.283333333333,
93.0756944444445, 83.5340277777778, 67.7833333333333, 65.3069444444444,
63.5402777777778, 59.6861111111111, 56.9791666666667, 55.9048611111111,
54.3826388888889, 52.6958333333333, 52.5125, 51.1680555555556,
50.9520833333333, 50.5402777777778, 49.9291666666667, 49.8201388888889,
49.7375, 49.0916666666667, 46.3069444444444, 45.30625, 45.2451388888889,
44.9722222222222, 44.8215277777778, 44.8048611111111, 43.0701388888889,
42.6840277777778, 42.6576388888889, 42.55, 42.2868055555556,
42.2805555555556, 41.9027777777778, 41.7409722222222, 41.6506944444444,
41.3527777777778, 40.7305555555556, 40.2861111111111, 40.2159722222222,
40.0854166666667, 40.0486111111111, 39.7930555555556, 39.6576388888889,
39.4638888888889, 39.4527777777778, 39.3569444444444, 39.3513888888889,
39.1854166666667, 39.0791666666667, 39.0743055555556, 39.0055555555556
)), row.names = c(NA, 50L), class = "data.frame")
I also have already extracted those in a separate dataframe:
quarts<- structure(list(min = 0, q1 = 7.1515625, median = 11.4881944444444,
mean = 12.3112423835125, q3 = 14.8456597222222, max = 93.0756944444445,
st_dev = 6.72704434885421, iqr = 7.69409722222222), class = "data.frame", row.names = c(NA,
-1L))
# A really basic boxplot.
ggplot(throu, aes( y=throughput_time)) +
geom_boxplot(fill="slateblue", alpha=0.2,width=0.05) +
xlim(-0.1, 0.1) +
xlab("")+ylab("Case duration in days")+ theme_classic()+
theme(axis.ticks.x = element_blank(),
axis.text.x = element_blank())
You could do this using annotate
ggplot(throu, aes( y=throughput_time)) +
geom_boxplot(fill="slateblue", alpha=0.2, width=0.05) +
annotate(geom = 'text', x = 0.05, y = 60, hjust = 0, color = 'gray50',
label = paste(names(quarts), collapse = '\n')) +
annotate(geom = 'text', x = 0.07, y = 60, hjust = 0,
label = paste(round(unlist(quarts), 3), collapse = '\n')) +
xlim(-0.1, 0.1) +
xlab("")+
ylab("Case duration in days")+
theme_classic()+
theme(axis.ticks.x = element_blank(),
axis.text.x = element_blank())

How to plot a chart with dual Y, both are bar plot with ggplot2?

I would like to plot a chart with dual Y, both are bar plot with ggplot2, and both bar with its own error bar and label, the following code fails. The bars overlaped, and the labels can not be displayed.
Thanks a lot.
df<- structure(list(dose = structure(1:3, .Label = c("0.5", "1", "2"
), class = "factor"), mean1 = c(13.23, 22.7, 26.06), sd1 = c(0.1,
0.2, 0.3), label = c("a", "b", "c"), mean2 = c(7.98, 16.77, 26.14
), sd2 = c(0.01, 0.2, 0.3), label2 = c("a", "b", "c")), row.names = c(NA,
-3L), class = "data.frame")
ggplot(df,aes(x = dose, fill = dose))+
geom_bar(aes(y = mean1), position = 'dodge', stat="identity", width=.4) +
geom_bar(aes(y = mean2/5), position = 'dodge', stat="identity", width=.4)+
scale_y_continuous(sec.axis = sec_axis(~. *5, name = "mean2"))+
geom_errorbar(aes(ymin = mean1, ymax = mean1 + sd1), width=.07,
position=position_dodge(0.4)) +
geom_errorbar(aes(ymin = mean2, ymax = mean2 + sd2), width=.07,
position=position_dodge(0.4))
geom_text(aes(y =mean1 + sd1, label = label1),vjust = -0.5, position=position_dodge(0.4))
geom_text(aes(y =mean2 + sd2, label = label2,),vjust = -0.5, position=position_dodge(0.4))
Is this what you are looking for? You just need to restructure your data so that it can be dodged by group.
bind_rows(
df |>
select(dose, label, mean = mean1, sd = sd1) |>
mutate(group = 1),
df |>
select(dose, label, mean = mean2, sd = sd2) |>
mutate(group = 2,
mean = mean/5)
) |>
ggplot(aes(x = dose, fill = dose, group = group))+
geom_bar(aes(y = mean), position = 'dodge', stat="identity", width=.4)+
geom_errorbar(aes(ymin = mean, ymax = mean + sd), width=.07,
position=position_dodge(0.4)) +
geom_text(aes(y =mean + sd, label = label),vjust = -0.5, position=position_dodge(0.4))+
scale_y_continuous(sec.axis = sec_axis(~. *5, name = "mean2"))

How to add common line and text as second x-axis label

I want to plot a graph. Several of my x-axis labels have a common label. So I want to add common text as label instead of several separate labels on x-axis as shown in the attached images. How can this be done?
library(dplyr)
library(forcats)
library(ggplot2)
df <- data.frame(conc = c(0, 10, 50, 100, "Positive Control"),
values = c(3, 3, 4, 5, 10),
name = c("TiO2 NP", "TiO2 NP", "TiO2 NP", "TiO2 NP", "Cyclophosamide"))
df$conc <- as.factor(df$conc)
labels2 <- paste0(df$conc, "\n", df$name)
df %>%
mutate(conc = fct_reorder(conc, values)) %>%
ggplot(aes(x = conc, y=values, fill = conc))+
geom_bar(stat = "identity",show.legend = FALSE, width = 0.6)+
scale_x_discrete(labels = labels2)+
labs(x = "\n Dose (mg/kg BW)")
I don't think there's a simple way. You have to play with ggplot2 for some time to make something really custom. Here's my example:
df %>%
mutate(
conc = fct_reorder(conc, values),
labels2 = if_else(
name == 'TiO2 NP',
as.character(conc),
paste0(conc, '\n', name)
)
) %>%
ggplot(aes(x=conc, y=values, fill = conc)) +
geom_bar(
stat = "identity",
show.legend = FALSE,
width = 0.6
) +
geom_rect(aes(
xmin = .4,
xmax = 5.6,
ymin = -Inf,
ymax = 0
),
fill = 'white'
) +
geom_text(aes(
y = -.4,
label = labels2
),
vjust = 1,
size = 3.4,
color = rgb(.3, .3, .3)
) +
geom_line(data = tibble(
x = c(.9, 4.1),
y = c(-1.2, -1.2)
),
aes(
x = x,
y = y
),
color = rgb(.3, .3, .3),
inherit.aes = FALSE
) +
geom_curve(data = tibble(
x1 = c(.8, 4.1),
x2 = c(.9, 4.2),
y1 = c(-.8, -1.2),
y2 = c(-1.2, -.8)
),
aes(
x = x1,
y = y1,
xend = x2,
yend = y2
),
color = rgb(.3, .3, .3),
inherit.aes = FALSE
) +
geom_text(aes(
x = 2.5,
y = -1.7,
label = 'TiO2 NP'
),
size = 3.4,
color = rgb(.3, .3, .3),
check_overlap = TRUE
) +
geom_text(aes(
x = 3,
y = -2.4,
label = '\n Dose (mg/kg BW)'
),
show.legend = FALSE,
check_overlap = TRUE
) +
theme_minimal() +
theme(
axis.text.x = element_blank(),
axis.title.x = element_blank()
) +
scale_y_continuous(
breaks = seq(0, 10, 2.5),
limits = c(-2.5, 10)
)
For a more automated approach, you can try placing the common variable in facet_grid with scales = "free", space = "free", to simulate a 2nd x-axis line. The rest of the code below are for aesthetic tweaks:
df %>%
mutate(conc = fct_reorder(conc, values)) %>%
ggplot(aes(x = conc, y = values, fill = conc)) +
geom_col(show.legend = F, width = 0.6) + #geom_col() is equivalent to geom_bar(stat = "identity")
facet_grid(~ fct_rev(name),
scales = "free", space = "free",
switch = "x") + #brings the facet label positions from top (default) to bottom
scale_x_discrete(expand = c(0, 0.5)) + #adjusts the horizontal space at the ends of each facet
labs(x = "\n Dose (mg/kg BW)") +
theme(axis.line.x = element_line(arrow = arrow(ends = "both")), #show line (with arrow ends) to
#indicate facet label's extent
panel.spacing = unit(0, "cm"), #adjusts space between the facets
strip.placement = "outside", #positions facet labels below x-axis labels
strip.background = element_blank()) #transparent background for facet labels

How do I send arrows which cover other labels to the back in geom_label_repel?

This should seem fairly straight forward but I can't find any argument to do this with ggrepel::geom_label_repel().
Sample of data:
df <- structure(list(Athletename = c("Aries Merritt", "Damian Warner"
), Score = c(12.8, 13.44), Event = c("110m hurdles", "110m hurdles"
), Points = c(1135, 1048), Record = c("World Record", "Decathlon Record"
), score_and_points = c("12.8s, 1135pts", "13.44s, 1048pts")), row.names = c(NA,
-2L), class = c("tbl_df", "tbl", "data.frame"), .Names = c("Athletename",
"Score", "Event", "Points", "Record", "score_and_points"))
ggplot2 code:
ggplot(data = data.frame(x = 0), mapping = aes(x = x)) +
geom_point(data = df, aes(x=Score, y=Points, colour=Record)) +
geom_label_repel(data = df,
aes(x=Score, y=Points, label = Athletename),
direction = "x",
nudge_x = -10) +
geom_label_repel(data = df,
aes(x=Score, y=Points, label = score_and_points),
direction = "y",
nudge_y = -200) +
scale_y_continuous(name = "Points",
breaks = seq(0,1500,100),
limits = c(0,1500)) +
scale_x_reverse(name = "110m hurdles time (m)",
breaks = seq(29,12,-1),
limits=c(29,12)) +
theme(legend.title = element_blank(), legend.position = "top")
Hacky but works: add a copy of the geom_label_repel call, but with the addition of segment.alpha = 0. Then all the labels will be on top of all the arrows.
library(ggrepel)
ggplot(data = data.frame(x = 0), mapping = aes(x = x)) +
geom_point(data = df, aes(x=Score, y=Points, colour=Record)) +
geom_label_repel(data = df,
aes(x=Score, y=Points, label = Athletename),
direction = "x",
nudge_x = -10) +
geom_label_repel(data = df,
aes(x=Score, y=Points, label = score_and_points),
direction = "y",
nudge_y = -200, ) +
geom_label_repel(data = df,
aes(x=Score, y=Points, label = score_and_points),
direction = "y", segment.alpha = 0,
nudge_y = -200, ) +
scale_y_continuous(name = "Points",
breaks = seq(0,1500,100),
limits = c(0,1500)) +
scale_x_reverse(name = "110m hurdles time (m)",
breaks = seq(29,12,-1),
limits=c(29,12)) +
theme(legend.title = element_blank(), legend.position = "top")

Extend bars on a ggplot2 to show the data labels not squished

Here is a data frame:
library(tidyverse)
example_df <- structure(list(Funnel = c("Sessions", "AddToCart", "Registrations", "ShippingDetails", "Checkout", "Transactions"), Sum = c(1437574, 385281, 148181, 56989, 35613, 29671), End = c(NA, 1437574, 385281, 148181, 56989, 35613), xpos = c(0.5, 1.5, 2.5, 3.5, 4.5, 5.5), Diff = c(NA, 1052293, 237100, 91192, 21376, 5942), Percent = c("NA %", "73.2 %", "61.5 %", "61.5 %", "37.5 %", "16.7 %")), .Names = c("Funnel", "Sum", "End", "xpos", "Diff", "Percent"), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -6L))
And here is a ggplot2:
ggplot(example_df, aes(x = reorder(Funnel, -Sum), y = Sum)) +
geom_col(alpha = 0.6, fill = "#008080") +
stat_summary(aes(label = scales::comma(..y..)), fun.y = 'sum',
geom = 'text', col = 'white', vjust = 1.5) +
geom_segment(aes(x=xpos, y = End, xend = xpos, yend = Sum)) +
geom_text(aes(x=xpos,y = End-Diff / 2, label=Percent), hjust = -0.2) +
theme(axis.title.x = element_blank(),
axis.title.y = element_blank()) +
scale_y_continuous(labels = function(l) {l = l / 1000; paste0(l, "K")}) +
Here's what it looks like:
The values on the plot from Shipping Details: Transactions are tricky to read because the bars are smaller.
I wondered if there was a good approach to dealing with this. I tried extending the range with:
+ expand_limits(y = -100000)
But that just lowers the y axis.
Is there a sensible solution to visualizing the data points in a way they are not squished? If I could somehow lower the green bars into the minus region without impacting the proportions?
Very dirty solution, but works. Add dummy geom_bar's bellow each segment (ie., extend original segment by adding negative bar) with the same color and alpha.
Bars to add:
geom_bar(data = data.frame(x = example_df$Funnel, y = -2e4),
aes(x, y),
stat = "identity", position = "dodge",
alpha = 0.6, fill = "#008080")
Final code:
# Using OPs data
library(ggplot2)
ggplot(example_df, aes(x = reorder(Funnel, -Sum), y = Sum)) +
geom_col(alpha = 0.6, fill = "#008080") +
geom_segment(aes(x=xpos, y = End, xend = xpos, yend = Sum)) +
geom_text(aes(x=xpos,y = End-Diff / 2, label=Percent), hjust = -0.2) +
theme(axis.title.x = element_blank(),
axis.title.y = element_blank()) +
scale_y_continuous(labels = function(l) {l = l / 1000; paste0(l, "K")}) +
geom_bar(data = data.frame(x = example_df$Funnel, y = -2e4),
aes(x, y),
stat = "identity", position = "dodge",
alpha = 0.6, fill = "#008080") +
stat_summary(aes(label = scales::comma(..y..)), fun.y = 'sum',
geom = 'text', col = 'white', vjust = 1.5) +
theme_classic()
Plot:
PS:
You have to add stat_summary after geom_bar

Resources