How can I implement histogram with such complex x-axis?
First x-axis row is the week start, second - week end.
Data for tests in csv: https://gofile.io/d/FrhLZh.
What I managed to
hist_data %>%
ggplot(aes(x = week, y = count)) +
geom_col(fill = "#5B879E", width = 0.9, size = 0.7) +
labs(title = "", x = "", y = "") +
theme_bw() + theme_minimal() + theme(legend.position="none")+
theme(
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.major.y = element_blank(),
panel.grid.minor.y = element_blank(),
axis.text.y = element_blank(),
axis.text.x = element_text(vjust = 0.5, size = 8, family = "Inter", colour = "#ffffff"),
axis.line.x = element_blank(),
axis.title.x = element_blank(),
plot.background = element_rect(fill = "#3A464F"),
plot.margin=unit(c(0,0.25,0.5,0), "cm"))+
scale_x_discrete(expand=c(0,0), labels = format(as.Date(hist_data$week_start), "%d-%m"), position = "bottom") +
scale_y_continuous()
Thanks to teunbrand and his ggh4x package, solution:
hist_data %>%
ggplot(aes(x = week, y = count)) +
geom_col(fill = "#5B879E", width = 0.8, size = 0.7)+
labs(title = "", x = "", y = "") +
theme_bw() + theme_minimal() + theme(legend.position="none")+
theme(
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.major.y = element_blank(),
panel.grid.minor.y = element_blank(),
axis.text.y = element_blank(),
axis.text.x = element_text(vjust = 0.5, size = 8, lineheight = 0.8, family = "Inter", colour = "#ffffff"),
axis.line.x = element_blank(),
axis.title.x = element_blank(),
ggh4x.axis.nestline.x = element_line(size = 0.5, colour = "#5B879E", lineend = "square"),
plot.background = element_rect(fill = "#3A464F"),
plot.margin=unit(c(1,0.5,1,0.5), "cm"))+
scale_x_discrete(expand=c(0,0),
labels = paste0(format(as.Date(sort(hist_data$week_start)), "%d.%m"),
"\n", "nonsense", "\n",
format(as.Date(sort(hist_data$week_end)), "%d.%m")), position = "bottom") +
scale_y_continuous() +
guides(x = guide_axis_nested(delim = "nonsense"))
You can add multiple layers of geom_text and geom_segment. Adjust the relative y positions of these layers using a scaling factor.
plotscale <- max(hist_data$count)/50
library(ggplot2)
ggplot(data = hist_data,
aes(x = week_start + floor(week_end-week_start)/2, y = count)) +
geom_col(fill = "#5B879E", width = 4) +
geom_text(aes(y = -6 * plotscale ,
label = format(week_start, "%m-%d")),
color = "#ffffff")+
geom_segment(aes(x = week_start, xend = week_end,
y = -10 * plotscale, yend = -10 * plotscale),
color = "#5B879E", size = 1.5)+
geom_text(aes(y = -14 * plotscale,
label = format(week_end, "%m-%d")),
color = "#ffffff")+
theme_minimal() +
theme(
panel.grid = element_blank(),
axis.text = element_blank(),
axis.title = element_blank(),
plot.background = element_rect(fill = "#3A464F"))+
scale_x_date(expand=c(0,0), date_breaks = "1 week",
labels = NULL)
Consider using ggh4x package for more complex nested x axes.
Raw Data
hist_data <- read.table(text='"","week","count","week_start","week_end"
"1","1",21.5823972708382,2021-01-04,2021-01-10
"2","2",36.122556304552,2021-01-11,2021-01-17
"3","3",34.2809483156697,2021-01-18,2021-01-24
"4","4",25.8546925450454,2021-01-25,2021-01-31
"5","5",29.0309819292706,2021-02-01,2021-02-07
"6","6",33.1503608888827,2021-02-08,2021-02-14
"7","7",27.0490347440184,2021-02-15,2021-02-21
"8","8",30.3031289757874,2021-02-22,2021-02-28
"9","50",32.2876434072602,2020-12-07,2020-12-13
"10","51",33.1939593686481,2020-12-14,2020-12-20
"11","52",26.6853246329896,2020-12-21,2020-12-27
"12","53",23.0715199391151,2020-12-28,2021-01-03', header = TRUE, sep = ",")
hist_data$week_start <- as.Date(hist_data$week_start)
hist_data$week_end <- as.Date(hist_data$week_end)
Related
I'm using ggplot to graph a forest plot. I have used facet labels to label groups (in example below Test1, Test2, Test3). Is there a way to slightly shift the actual position of the facet label/strip to the left (as indicated by the arrows in my picture below)?
I can shift the position of the text within the facet label but I think I have done that as much as possible. Thus, I think I need to shift the actual facet label (strip bar/rectangle) itself. Is this possible?
Would be very grateful if anyone could help me or point out a way to get a similar effect!
Please find reproducible code here:
library(dplyr)
library(ggplot2)
library(ggforce)
library(tidyverse)
# Reproducible dataset
df <- data.frame(outcome = c('outcome1', 'outcome1', 'outcome2','outcome2','outcome3','outcome3','outcome4','outcome4','outcome5','outcome5'),
type = c('Test1','Test1','Test2','Test2', 'Test3', 'Test3', 'Test3','Test3', 'Test3', 'Test3'),
Coef = c(0.10026935, 0.10026935, 0.13713358, 0.13713358,0.07753188,0.07753188,0.09193794,0.09193794,0.06170916,0.06170916),
CIr_low = c(0.070955475,0.070955475,0.108705781,0.108705781,0.052595474,0.052595474,0.056340327,0.056340327,0.036185918,0.036185918),
CIr_high = c(0.12958323,0.12958323,0.16556139,0.16556139,0.10246828,0.10246828,0.12753555,0.12753555,0.08723240,0.08723240),
model = c(1,2,1,2,1,2,1,2,1,2))
# Set type as factor
df <- df %>% mutate(type = fct_relevel(type, "Test1","Test2","Test3"))
# Plot with ggplot
ggplot(df, aes(x = outcome, y = Coef, ymin = CIr_low,ymax =CIr_high,fill = as.factor(type))) +
geom_errorbar(aes(x= outcome, ymin=CIr_low, ymax=CIr_high), width=0.2,cex=0.5)+
geom_point(shape = 18, size = 5)+
facet_grid(type ~ ., scales = "free", space = "free") +
geom_hline(yintercept = 0, linetype = 'dashed', col = 'black') +
scale_y_continuous(limits = c(-0.1, 0.25)) +
ggforce::facet_col(facets = type ~ ., scales = "free_y", space = "free", strip.position = "top")+
theme_bw()+
coord_flip() +
xlab('Group')+
ylab(expression("Standardized" ~ beta *" (95%CI)"))+
theme(line = element_line(colour = "black", size = 0.5),
plot.margin = margin(0.5, 0.5, 0.5, 0.5, unit = "cm"),
strip.background = element_rect(colour = "white", fill="white"),
strip.text = element_text(colour = "black",face="italic"),
strip.text.x = element_text(size = 12,angle = 0,hjust = 0,face="bold.italic", color="darkblue"),
legend.position ="none",
axis.line.x = element_line(colour = "black"),
axis.line.y = element_blank(),
panel.border= element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
panel.spacing = unit(2, "lines"),
axis.ticks = element_blank(),
axis.title.x = element_text(colour = "black"),
axis.title.y = element_blank(),
axis.text=element_text( color = "black")
)
You can try:
ggplot(df, aes(x = outcome, y = Coef, ymin = CIr_low,ymax =CIr_high,fill = as.factor(type))) +
geom_errorbar(aes(x= outcome, ymin=CIr_low, ymax=CIr_high), width=0.2,cex=0.5)+
geom_point(shape = 18, size = 5, show.legend = F)+
geom_hline(yintercept = 0, linetype = 'dashed', col = 'black') +
scale_y_continuous(expression("Standardized" ~ beta *" (95%CI)"),limits = c(-0.1, 0.25)) +
xlab("")+
coord_flip() +
facet_grid(type~., scales = "free", space = "free_y", switch = "y") +
theme_minimal() +
theme(strip.placement = "outside",
strip.text.y.left = element_text(angle = 0,vjust = 1,size=12))
Or use a cowplot approach with ggtitle
plots <- df %>%
split(.$type) %>%
map2(.,names(.), ~ggplot(.x, aes(x = outcome, y = Coef, ymin = CIr_low,ymax =CIr_high,fill = as.factor(type))) +
geom_errorbar(aes(x= outcome, ymin=CIr_low, ymax=CIr_high), width=0.2, size=0.5)+
geom_point(shape = 18, size = 5, show.legend = F)+
geom_hline(yintercept = 0, linetype = 'dashed', col = 'black') +
scale_y_continuous(limits = c(-0.1, 0.25))+
coord_flip() +
xlab('')+
ylab(expression("Standardized" ~ beta *" (95%CI)"))+
ggtitle(.y)+
theme_minimal(base_size = 12)+
theme( panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
plot.title.position = "plot"))
cowplot::plot_grid(plots$Test1 + theme(axis.title.x = element_blank(), axis.ticks.x = element_blank(), axis.text.x = element_blank()),
plots$Test2 + theme(axis.title.x = element_blank(), axis.ticks.x = element_blank(), axis.text.x = element_blank()),
plots$Test3, ncol = 1)
I have plotted a donut chart with the code below:
library(tidyverse)
library(ggthemes)
df <- data.frame(flavor = c("Chocolate", "Strawberry", "Pistachio"),
per_sold = c(.20, .30, .50))
df %>%
ggplot(aes(x = 2, y = per_sold, fill = flavor)) +
geom_bar(stat = "identity") +
xlim(0.5, 2.5) +
coord_polar(start = 0, theta = "y") +
xlab("") +
ylab("") +
theme(axis.ticks = element_blank(),
axis.text = element_blank(),
axis.title = element_blank(),
panel.grid = element_blank(),
panel.border = element_blank(),
legend.title = element_text(size = rel(2)),
legend.text=element_text(size=rel(1.5))) +
geom_text(aes(label = per_sold), size = 6)
Out:
As you can see, the position of labels are not correct, also I want it show the format of % instead of float number with digit.
How could I modify the code to achive this? Thanks.
All you need is position_stack(vjust = 0.5) and scales::percent:
library(scales)
df %>%
ggplot(aes(x = 2, y = per_sold, fill = flavor)) +
geom_bar(stat = "identity") +
xlim(0.5, 2.5) +
coord_polar(start = 0, theta = "y") +
xlab("") +
ylab("") +
theme(axis.ticks = element_blank(),
axis.text = element_blank(),
axis.title = element_blank(),
panel.grid = element_blank(),
panel.border = element_blank(),
legend.title = element_text(size = rel(2)),
legend.text=element_text(size=rel(1.5))) +
geom_text(aes(label = scales::percent(per_sold)),
size = 6, position = position_stack(vjust = 0.5))
I have run the following ggplot function :
g <- ggplot(results_table, aes(x = "", y = Pct*100, fill = Criteria),width = 0.5) +
geom_bar(stat = "identity", color = Palcolor, fill = Palcolor) +
coord_polar(theta = "y", start = 0, direction = -1) +
theme_minimal() +
theme(legend.position = "none", axis.title.x = element_blank(), axis.title.y = element_blank(),
panel.border = element_blank(), panel.grid = element_blank(), axis.text = element_blank(),
axis.ticks = element_blank(), legend.title = element_blank(),
plot.title = element_text(size = 14, hjust = 0.5, vjust = 0)) +
geom_text(aes(label = paste0(Criteria,"; ",sprintf("%0.1f", round(Pct*100, digits = 1)),"%")),
position = position_stack (vjust = 0.5, reverse = TRUE)) +
labs(title = gTitle)
}
and the pie is the following :
but it is too large. I would like to have a diameter smaller than the length of the second part of the title. How can I proceed ?
I have run the following code :`
g <- ggplot(results_table, aes(x = "", y = Pct*100, fill = Criteria),width = 1) +
geom_bar(stat = "identity", color = Palcolor, fill = Palcolor) +
coord_polar(theta = "y", start = 0) +
theme_minimal() +
theme(legend.position = "bottom", legend.title=element_blank(), axis.title.x = element_blank(),,
axis.title.y = element_blank(), panel.border = element_blank(), panel.grid = element_blank(),
axis.text = element_blank(), axis.ticks = element_blank(),
plot.title = element_text(size = 14, hjust = 0.5, vjust = 0)) +
guides(fill = guide_legend(nrow = 4, byrow = TRUE)) +
theme(
legend.key.height = unit(0.3, "lines"), #smaller squares
legend.key.width = unit(0.7, "lines"), #smaller squares
legend.margin=margin(l = 40, unit='pt'),
legend.text = element_text(margin = margin(r = 60, unit = "pt"))) +
xlab("") +
ylab("") +
geom_text(aes(x = 1.70, y = Pct*100/2 + c(0, cumsum(Pct*100)[-length(Pct*100)]),
label = paste0(sprintf("%0.1f", round(Pct*100, digits = 1)),"%")),
size = 3.2) +
labs(title = gTitle)
}`
It created the pie chart as expected, but not the customized legend :
Any idea ?
The problem is that you set the custom color and fill palettes as arguments inside geom_bar. This way no legend will show up. You have to use scale_color/fill_manual to set the color palettes for the color/fill aesthetics.
Using ggplot2::mpg as example data and an example palette from RColorBrewer try this:
library(ggplot2)
library(dplyr)
# Example data
results_table <- mpg %>%
count(class) %>%
mutate(Pct = n / sum(n),
class = reorder(class, Pct)) %>%
rename(Criteria = class) %>%
arrange(desc(Pct)) %>%
mutate()
# Example palette as named vector to get the colors and categories right
Palcolor <- c("2seater" = "#8DD3C7", "minivan" = "#FFFFB3", "pickup" = "#BEBADA", "subcompact" = "#FB8072", "midsize" = "#80B1D3", "compact" = "#FDB462", "suv" = "#B3DE69")
# Example title
gTitle = "Example title"
g <- ggplot(results_table, aes(x = "", y = Pct*100, fill = Criteria),width = 1) +
geom_bar(stat = "identity") +
scale_color_manual(values = Palcolor) +
scale_fill_manual(values = Palcolor) +
coord_polar(theta = "y", start = 0) +
theme_minimal() +
theme(legend.position = "bottom", legend.title=element_blank(), axis.title.x = element_blank(),,
axis.title.y = element_blank(), panel.border = element_blank(), panel.grid = element_blank(),
axis.text = element_blank(), axis.ticks = element_blank(),
plot.title = element_text(size = 14, hjust = 0.5, vjust = 0)) +
guides(fill = guide_legend(nrow = 4, byrow = TRUE)) +
theme(
legend.key.height = unit(0.3, "lines"), #smaller squares
legend.key.width = unit(0.7, "lines"), #smaller squares
legend.margin=margin(l = 40, unit='pt'),
legend.text = element_text(margin = margin(r = 60, unit = "pt"))) +
xlab("") +
ylab("") +
geom_text(aes(x = 1.70, y = Pct*100/2 + c(0, cumsum(Pct*100)[-length(Pct*100)]),
label = paste0(sprintf("%0.1f", round(Pct*100, digits = 1)),"%")),
size = 3.2) +
labs(title = gTitle)
g
Created on 2020-05-16 by the reprex package (v0.3.0)
I created this plot using facet_grid and patchwork because I needed to have a customized secondary y-axis for each of the parameter and they all have different scale. I have successfully tweaked most of the aesthetics to match with what I need for the graph except for a couple of places:
Matching color with "site." I would like to match red, blue, and green to Port, Bluff, and Palm respectively. It didn't work with the code I have in scale_color_manual.
Renaming the strip text. I tried using expression(paste()) before but it wasn't working, especially with greek letter. I would like to have these respective stip text on the right for each row: ETR[max], ɑ, and E[k].
Letter in the [] are subscripts.
Thank you for any pointers. I ran out of things to try to make this week, especially with the strip texts.
My dataframe: data file
My codes are:
abrv_mo <- with (params, month.abb[month]) params <- transform(params, month = abrv_mo) params <- params[order(match(params$month, month.abb)), ] params$month <- factor(params$month, month.abb, ordered = TRUE) params$month<- as.Date(ISOdate(2019, as.numeric(params$month), 15))
p1 <- ggplot() + geom_hline(yintercept = 19.6, linetype = "dashed")
+ geom_line(data = tmpr2,
aes(month, tmp*0.98),
alpha = 0.4) + geom_errorbar(data = subset(params, variable == "max"),
aes(x= month, ymin = mean - se, ymax = mean +se, color = site),
width = 8) + geom_point(data = subset(params, variable == "max"),
aes(x=month, y=mean, color = site, group=site),
size = 2.5) + facet_grid(rows = vars(variable),
cols = vars(site),
switch = "y", scale = "free_y") + scale_x_date(name = NULL, date_labels = "%b",
seq(as.Date("2019-01-15"),
as.Date("2019-07-15"), by = "1 month")) + # ?strftime() for more options scale_y_continuous(limits = c(5,40), breaks = seq(5, 40, by = 15),
expand = c(0,0),
sec.axis = sec_axis(~./0.98)) + scale_color_manual(name = "Site",
labels = c("Port", "Bluff", "Palm"),
values = c("#FC4E07","#00AFBB", "#C3D7A4")) + theme_bw() + theme(plot.background = element_blank(),
strip.background = element_blank(),
strip.placement = "outside",
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_rect(size=1, colour = "black"),
panel.spacing = unit(0.3, "lines"),
axis.line = element_line(size=0.1, colour = "black"),
axis.ticks.y = element_line(size=0.5, colour = "black"),
axis.text.x = element_blank(),
axis.text.y = element_text(size=10, color="black", margin = margin(t = 0.5, l = 0.5)),
text = element_text(size = 18),
legend.position="none",
plot.margin=margin(l = -1, unit = "cm")) + ylab(NULL)
p2 <- ggplot() + geom_hline(yintercept = 0.16, linetype = "dashed")
+ geom_line(data = tmpr2,
aes(month, tmp*0.008),
alpha = 0.4) + geom_errorbar(data = subset(params, variable=="slope"),
aes(x= month, ymin = mean - se, ymax = mean +se, color = site),
width = 8) + geom_point(data = subset(params, variable == "slope"),
aes(x=month, y=mean, color=site, group=site),
size = 2.5) + facet_grid(rows = vars(variable),
cols = vars(site),
switch = "y",
scale = "free_y") + scale_x_date(name = NULL, date_labels = "%b",
seq(as.Date("2019-01-15"),
as.Date("2019-07-15"), by = "1 month")) + # ?strftime() for more options scale_y_continuous(breaks = seq(0.15,
0.26, by = 0.05),
expand = c(0,0),
limits = c(0.15,0.26),
sec.axis = sec_axis(~./0.008, name = "Temperature (°C)")) + scale_color_manual(name = "Site",
labels = c("Port", "Bluff", "Palm"),
values = c("#FC4E07","#00AFBB", "#C3D7A4")) + theme_bw() + theme(plot.background = element_blank(),
strip.background = element_blank(),
strip.placement = "outside",
strip.text.x = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_rect(size=1, colour = "black"),
panel.spacing = unit(0.3, "lines"),
axis.line = element_line(size=0.1, colour = "black"),
axis.ticks.y = element_line(size=0.5, colour = "black"),
axis.text.x = element_blank(),
axis.text.y = element_text(size=10, color="black", margin = margin(t = 0.5, l = 0.5)),
axis.text.y.right = element_text(size=10, color="black", margin = margin(t = 0.5, r = 10)),
text = element_text(size = 18),
legend.position="none",
plot.margin=margin(l = -1.5, unit = "cm")) + ylab(NULL)
p3 <- ggplot() + geom_hline(yintercept = 140, linetype = "dashed") + geom_line(data = tmpr2,
aes(month, tmp*7),
alpha = 0.4) + geom_errorbar(data = subset(params, variable=="ek"),
aes(x= month, ymin = mean - se, ymax = mean +se, color = site),
width = 8) + geom_point(data = subset(params, variable=="ek"),
aes(x=month, y=mean, color=site, group=site),
size = 2.5) + facet_grid(rows = vars(variable),
cols = vars(site),
switch = "y",
scale = "free_y") + scale_x_date(name = NULL, date_labels = "%b",
seq(as.Date("2019-01-15"),
as.Date("2019-07-15"), by = "1 month")) + # ?strftime() for more options scale_y_continuous(expand = c(0,0),
breaks = seq(25, 250, by = 100),
limits = c(25,250),
sec.axis = sec_axis(~./7)) + scale_color_manual(name = "Site",
labels = c("Port", "Bluff", "Palm"),
values = c("#FC4E07","#00AFBB", "#C3D7A4")) + theme_bw() + theme(plot.background = element_blank(),
strip.background = element_blank(),
strip.placement = "outside",
strip.text.x = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_rect(size=1, colour = "black"),
panel.spacing = unit(0.3, "lines"),
axis.line = element_line(size=0.1, colour = "black"),
axis.ticks.y = element_line(size=0.5, colour = "black"),
axis.text.x = element_text(angle = 45,size=10, color="black", hjust = 1,
margin = margin(t = 0.5, r = 0.5)),
axis.text.y = element_text(size=10, color="black", margin = margin(t = 0.5, l = 0.5)),
text = element_text(size = 18),
legend.position="none",
plot.margin=margin(l = -1.5, unit = "cm")) + ylab(NULL)
library(patchwork)
p1 + p2 + p3 + plot_layout(ncol = 1)