Customize order of y-axis label in ggplot - r

When I run the code order of y-axis label is changed alphabetically, but I want to keep it as like as my coef column of new.table dataset. Here is my code:
library(ggplot2)
library(dplyr)
library(data.table)
coef<-c("<=40 years", "41-55 years", "56+ years", "Underweight", "Normal",
"Overweight", "Obese", "Uncontrolled", "Control", "Uncontrolled", "Control",
"< 5 years", "5-10 years", ">= 10 years", "Adherence", "Non-adherence")
or<-c(1,0.98, 1.16, 1.68, 1, 0.59, 0.71, 2.57, 1, 1.1, 1, 1, 2.03, 9.51, 1, 1.82)
ci_lb<-c(1, 0.41, 0.47, 0.25, 1, 0.33, 0.34, 1.3, 1, 0.63, 1, 1, 0.81, 3.85, 1, 1.07)
ci_ub<-c(1, 2.35, 2.87, 11.22, 1, 1.03, 1.48, 5.08, 1, 1.92, 1, 1, 5.09, 23.46, 1, 3.1)
term<-c("Age", "Age", "Age", "BMI", "BMI", "BMI", "BMI", "FBS", "FBS", "SBP", "SBP", "Duration", "Duration", "Duration", "Drug", "Drug")
is.reference<-rep(TRUE,16)
new.table<-data.frame(coef, or, ci_lb, ci_ub, term, is.reference)
p <- ggplot(new.table,
aes(x = or, xmin = ci_lb, xmax = ci_ub,
y = coef, color = term)) + coord_cartesian(xlim=c(0,25))+
geom_vline(xintercept = 1, linetype = "longdash") +
geom_errorbarh(height = 0.2) +
geom_point(size = 2, shape = 18) +
facet_grid(term~., scales = "free_y", space = "free_y")+
scale_alpha_identity()

To extend my comment a bit, we need to set factor order on coef and on term, then reverse y axis:
# factor
new.table$coef <- factor(new.table$coef, levels = unique(new.table$coef))
new.table$term <- factor(new.table$term, levels = unique(new.table$term))
ggplot(new.table,
aes(x = or, xmin = ci_lb, xmax = ci_ub,
y = coef, color = term)) + coord_cartesian(xlim=c(0,25))+
geom_vline(xintercept = 1, linetype = "longdash") +
geom_errorbarh(height = 0.2) +
geom_point(size = 2, shape = 18) +
facet_grid(term~., scales = "free_y", space = "free_y")+
scale_alpha_identity() +
# flip y-axis
scale_y_discrete(limits = rev)

Related

How fill geom_ribbon with different colour in R?

I am trying to use different fill for geom_ribbon according to the x-values (For Temp = 0-20 one fill, 20-30.1 another fill and > 30.1 another fill). I am using the following code
library(tidyverse)
bounds2 <- df %>%
mutate(ymax = pmax(Growth.rate, slope),
ymin = pmin(Growth.rate, slope),
x_bins = cut(Temp, breaks = c(0,20,30.1,max(Temp)+5)))
ggplot(df, aes(x = Temp, y = Growth.rate)) +
geom_line(colour = "blue") +
geom_line(aes(y = slope), colour = "red") +
scale_y_continuous(sec.axis = sec_axis(~ .^1, name = "slope")) +
geom_ribbon(data = bounds2, aes(Temp, ymin = ymin, ymax = ymax, fill = x_bins),
alpha = 0.4)
It is returning me following output
As you can see from the output some regions are remaining empty. Now how can I fill those parts in the curve?
Here is the data
df = structure(list(Temp = c(10, 13, 17, 20, 25, 28, 30, 32, 35, 38
), Growth.rate = c(0, 0.02, 0.19, 0.39, 0.79, 0.96, 1, 0.95,
0.65, 0), slope = c(0, 0.02, 0.16, 0.2, 0.39, 0.1, 0.03, -0.04,
-0.29, -0.65)), row.names = c(NA, 10L), class = "data.frame")
Here's a solution that involves interpolating new points at the boundaries between the areas. I used approx to get the values of ymin and ymax at Temp=30.1 and added this to the plotting dataset.
Then, instead of using cut just once as you did I use it twice, once with lower bounds included in each set then once with upper bounds included. Then I reshape the data long, and de-duplicate the rows I don't need.
If you zoom in enough you can see that the boundary is at 30.1 not at 30.
bounds2 <- df %>%
mutate(ymax = pmax(Growth.rate, slope),
ymin = pmin(Growth.rate, slope))
bounds2 <- bounds2 |>
add_case(Temp=30.1,
ymax=approx(bounds2$Temp,bounds2$ymax,xout = 30.1)$y,
ymin=approx(bounds2$Temp,bounds2$ymin,xout = 30.1)$y) |>
mutate(x_bins2 = cut(Temp, breaks = c(0,20,30.1,max(Temp)+5),right=FALSE, labels=c("0-20","20-30.1","30.1-max")),
x_bins = cut(Temp, breaks = c(0,20,30.1,max(Temp)+5), labels=c("0-20","20-30.1","30.1-max"))) |>
tidyr::pivot_longer(cols=c(x_bins2, x_bins), names_to = NULL, values_to = "xb") |>
distinct()
ggplot(df, aes(x = Temp, y = Growth.rate)) +
geom_line(colour = "blue") +
geom_line(aes(y = slope), colour = "red") +
scale_y_continuous(sec.axis = sec_axis(~ .^1, name = "slope")) +
geom_ribbon(data = bounds2, aes(Temp, ymin = ymin, ymax = ymax, fill = xb),
alpha = 0.4)
The idea is here but the code I show can be much improved at the step ### Dupplicate the 2 last x_bins from each category and move them into the next
### Libraries
library(tidyverse)
df <- structure(list(Temp = c(10, 13, 17, 20, 25, 28, 30, 32, 35, 38
), Growth.rate = c(0, 0.02, 0.19, 0.39, 0.79, 0.96, 1, 0.95,
0.65, 0), slope = c(0, 0.02, 0.16, 0.2, 0.39, 0.1, 0.03, -0.04,
-0.29, -0.65)), row.names = c(NA, 10L), class = "data.frame")
### Preprocessing
bounds2 <- df %>%
mutate(ymax = pmax(Growth.rate, slope),
ymin = pmin(Growth.rate, slope),
x_bins = cut(Temp, breaks = c(0, 20, 30.1, max(Temp)+5)))
### Dupplicate the 2 last x_bins from each category and move them into the next category
bounds2 <- rbind(bounds2, bounds2[c(4, 7), ])
bounds2$x_bins[c(11, 12)] <- bounds2[c(5, 8), ]$x_bins
### Plot
ggplot(df, aes(x = Temp, y = Growth.rate)) +
geom_line(colour = "blue") +
geom_line(aes(y = slope), colour = "red") +
scale_y_continuous(sec.axis = sec_axis(~ .^1, name = "slope")) +
geom_ribbon(data = bounds2, aes(Temp, ymin = ymin, ymax = ymax, fill = x_bins),
alpha = 0.4)

How to add a new (custom) variable to a ggplot legend

I've run a number of models with two estimated parameters per model with five groups and two treatments. I'm trying to graph the confidence intervals of these estimates in a large panel plot. Since, I've simulated these data sets I would like to be able to include a dashed line for the "true value" of the parameter which I set at the beginning of the exercise for reference so we can see how well the confidence interval of the model estimates includes the true value. I can do this just fine but I'd like to include another line in the legend that shows "dashed black line" = True Value.
Here's an example of the code. The first set of code works and does not include the dashed black line in the legend.
group = c("group1", "group2", "group3", "group4", "group5")
treatment = c("treatment1", "treatment2")
estimates = c("estim1", "estim2")
parameters = c("param1", "param2")
means = c(0, 0, 5, 0, -5, 0, 0, 7, -5, 10, -5, 0, 0, 0, 0, 0, -5, 0, 0, 10)
UL = c(.5, .5, 5.5, .5, -4.5, 0.5, 0.5, 7.5, -4.5, 10.5, -4.5, .5, .5, .5, .5, .5, -4.5, .5, .5, 10.5)
LL = c(-.5, -.5, 4.5, -.5, -5.5, -.5, -.5, 6.5, -4.5, 9.5, -4.5, -.5, -.5, -.5, -.5, -.5, -4.5, -.5, -.5, 9.5)
values = c(.2, -.2, 5.2, -.3, -4.7, -.1, -.2, 6.9, -5.3, 10.1, -4.4, 0.1, 0.2, 0.3, 0.1, -0.1, -4.9, -.2, -.2, 9.9)
df = data.frame(
group = rep(rep(group, each = 2), 2),
treatment = rep(treatment, each = 10),
estimates = rep(estimates, 10),
LL = LL,
means = means,
UL = UL,
parameters = rep(parameters, 10),
values = values
)
ggplot(data = df, aes(x = as.factor(estimates), y = means, color = estimates))+
geom_point()+
geom_errorbar(aes(ymin = LL, ymax = UL), width=.1, position = position_dodge(0.1))+
geom_segment(x = rep(c(.6, 1.6), 10), xend = rep(c(1.4, 2.4), 10),
y = values, yend = values, col = "black",
linetype = 3)+
scale_x_discrete(labels = c(expression(beta[1]), expression(beta[2])))+
xlab("Beta coefficient type")+ylab("Confidence Interval of Estimate")+
ggtitle("Coefficient Estimates")+
facet_grid(row = vars(treatment), col = vars(group))+
scale_color_manual(name = "Symbols",
values = c("estim1" = "#F8766D", "estim2" = "#00BFC4"),
labels = c(expression(beta[1]),
expression(beta[2])))
scale_shape_manual(values = c("b1" = 16,
"b2" = 16)+
scale_linetype_manual(values = c("b1" = 1,
"b2" = 1))
The second set of code, does not work but is my best attempt as to what maybe I should do to try to get the dashed black line in the legend.
ggplot(data = df, aes(x = as.factor(estimates), y = means, color = estimates))+
geom_point()+
geom_errorbar(aes(ymin = LL, ymax = UL), width=.1, position = position_dodge(0.1))+
geom_segment(x = rep(c(.6, 1.6), 10), xend = rep(c(1.4, 2.4), 10),
y = values, yend = values, col = "black",
linetype = 3)+
scale_x_discrete(labels = c(expression(beta[1]), expression(beta[2])))+
xlab("Beta coefficient type")+ylab("Confidence Interval of Estimate")+
ggtitle("Coefficient Estimates")+
facet_grid(row = vars(treatment), col = vars(group))+
scale_color_manual(name = "Symbols",
values = c("estim1" = "#F8766D", "estim2" = "#00BFC4"),
#"" = "#00000"),
labels = c(expression(beta[1]),
expression(beta[2])))#,
#"True Value"))#+
scale_shape_manual(values = c("b1" = 16,
"b2" = 16,
"" = 0))+
scale_linetype_manual(values = c("b1" = 1,
"b2" = 1,
"b3" = 3))
I've also thought that maybe I could include try to relevel the df$estimates column to include three levels (the existing) "estim1", "estim2" and a dummy "True Value" level with no observations but I'm worried that this would just add an empty "True Value" tick to each of my 12 plots on the x-axis sublabels.
Thanks for you help.
Map the linetype of your geom_segment to a string called "True value" inside aes, then add a scale_linetype_manual call. This will create a separate legend entry that matches the appearance of your segment and has the correct label.
ggplot(data = df, aes(x = as.factor(estimates), y = means, color = estimates)) +
geom_point() +
geom_errorbar(aes(ymin = LL, ymax = UL), width=.1,
position = position_dodge(0.1)) +
geom_segment(x = rep(c(.6, 1.6), 10), xend = rep(c(1.4, 2.4), 10),
y = values, yend = values, col = "black",
aes(linetype = "True value")) +
scale_x_discrete(labels = c(expression(beta[1]), expression(beta[2]))) +
xlab("Beta coefficient type")+ylab("Confidence Interval of Estimate") +
ggtitle("Coefficient Estimates") +
facet_grid(row = vars(treatment), col = vars(group)) +
scale_color_manual(name = "Symbols",
values = c("estim1" = "#F8766D", "estim2" = "#00BFC4"),
labels = c(expression(beta[1]),
expression(beta[2]))) +
scale_linetype_manual(values = 3, name = NULL)

Forcing specific plot symbols for points in R ggplot2

I am trying to specify manually, the shape of data points in r ggplot2 but can't seem to get it to work. Below is a sample example
p.est<- c(1.65, 1.55, 0.70, 1.61, 1.25)
lcl<-c(1.25, 1.10, 0.50, 1.20, 1.02)
ucl<-c(2.20, 2.05, 0.90, 2.20, 1.50)
toy.data <- tibble(zc = zc, p.est = p.est, p.lcl = p.lcl, p.ucl = p.ucl)
Assume I want two types of plot symbols for the five points, I use scale_shape_manual() in ggplot2 but it doesn't seem to work. Below is my sample code and the resulting plot attached. I'm trying to modify so the plot symbols for the points correspond to 5 which is a diamond and 16 which is a circle.
ggplot(toy.data, aes(zc, p.est, ymin = p.lcl, ymax = p.ucl)) +
scale_shape_manual(values = c(5, 16, 5, 5, 16))+
geom_pointrange(position = position_dodge(width = 0.1))+
geom_hline(yintercept = 1)+
ylim(0.5, 2.5)
You can add shape = factor(p.est). Otherwise scale_shape doesn't apply to anything.
zc <- c(1,2,3,4,5)
p.est <- c(1.65, 1.55, 0.70, 1.61, 1.25)
p.lcl <-c(1.25, 1.10, 0.50, 1.20, 1.02)
p.ucl <-c(2.20, 2.05, 0.90, 2.20, 1.50)
toy.data <- tibble(zc = zc,
p.est = p.est,
p.lcl = p.lcl,
p.ucl = p.ucl)
ggplot(toy.data, aes(zc, p.est, ymin = p.lcl, ymax = p.ucl, shape = factor(p.est))) +
scale_shape_manual(values = c(5, 16, 5, 5, 16)) +
geom_pointrange(position = position_dodge(width = 0.1)) +
geom_hline(yintercept = 1) +
ylim(0.5, 2.5)
EDITED Follow up question
toy.data <- tibble(zc = zc,
p.est = p.est,
p.est.x = c("A","B","A","A","B"),
p.lcl = p.lcl,
p.ucl = p.ucl)
ggplot(toy.data, aes(zc, p.est, ymin = p.lcl, ymax = p.ucl, shape = p.est.x)) +
scale_shape_manual(values = c(5, 16)) +
geom_pointrange(position = position_dodge(width = 0.1)) +
geom_hline(yintercept = 1) +
ylim(0.5, 2.5)

Different colors in ggplot when you upload a file vs. when you create a data of your own in R

So, I have a dataset in .csv format, which is attached here, and I want to make the following graph in ggplot2.
df1 <- read.csv("obesity.csv")
ggplot(df1, aes(x = Levels, y = OR, color = col)) +
geom_point(size = 3) +
geom_errorbar(aes(ymax = UCI, ymin = LCI), width = 0.3) +
coord_flip() +
facet_grid(name ~ ., scales = "free_y", space = "free_y", switch = "y") +
geom_hline(yintercept = 1, size=1, col="brown") +
scale_x_discrete(position = "top") +
theme_bw() +
scale_color_manual(guide = FALSE, values = c("red", "blue", "black", "green", "orange",
"chocolate", "brown", "grey", "tomato", "navyblue", "purple1", "orchid4"))
As you can see the order of colors are completely different than what I chose.
However, if I create the data in R by myself, then there is no problem.
df2 <- data.frame(
Levels = as.factor(c("Africa", "Europe", "Latin America", "Middle East", "High",
"Upper middle", "Lower middle", "Secondary", "Post-Secondary", ">= 9 years", "Male",
"> 60 min/day")),
OR = c(0.72, 3.17, 0.51, 0.51, 0.38, 0.94, 1.04, 2.22, 3.49, 2.24, 1.9, 0.44),
LCI = c(0.23, 0.68, 0.09, 0.2, 0.09, 0.29, 0.49, 0.72, 1.33, 1.14, 0.93, 0.19),
UCI = c(2.28,9.5,2.92,1.32,1.62,3.07,2.22,6.77,9.16,4.39,3.87,1.03),
name = as.factor(c("Region", "Region", "Region", "Region", "Income", "Income",
"Income", "Education", "Education", "Age", "Sex", "PAL")),
col = paste("col",1:12, sep=""))
Now, I am trying to understand what is the difference between the 2, and how can I set colors the same way as I want, when I am using a dataset in csv format.
Edit: I changed the variables in df2 to be factors, not characters.

ggplot2 v2.21.9 sec.axis in polar plot

I am currently trying to add a secondary axis using the recently introduced function sec.axis in ggplot2. This function works well with scatter/bar plots, but not for polar plot: In the following code, the name for the second y-axis appears, but not the axis.
Is there any workaround or option, that I have not figured out?
require(ggplot2)
set.seed(40);
Location <- data.frame(Winkel = round(runif(1000, 0, 24), 0))
Location$BAD <- Location$Winkel %in% c(seq(7, 18))
Abschnitte <- c(0:24)
polar <- data.frame(Winkel2 = c(1.5, 2.34, 1.2, 3.45, 1.67, 2.61, 1.11, 13.2),
value = c(0.1, 0.03, 0.02, 0.015, 0.01, 0.04, 0.09, 0.06))
ggplot(Location, aes(x = Winkel, fill = BAD, y = (..count..)/sum(..count..))) +
geom_histogram(breaks = seq(0,24), colour = "black") +
coord_polar(start = 0) + theme_minimal() +
scale_fill_brewer(type = "seq", palette = 3) +
ylab("Percentual allocation time") +
ggtitle("") +
scale_x_continuous("", limits = c(0, 24), breaks = Abschnitte, labels = Abschnitte) +
scale_y_continuous(labels = scales::percent,
sec.axis = sec_axis(~.*5, name = "mean direction")) +
geom_segment(data = polar, aes(x = Winkel2, y = 0, xend = Winkel2, yend = value, fill = NA),
arrow = arrow(angle = 30, type = "closed", length = unit(0.3, "cm")))
As #henrik mentioned in the comments, this is a bug. It's been patched and is available if you use the development version from GitHub (i.e., devtools::install_github("tidyverse/ggplot2")).
Here's the example after the patch:
require(ggplot2)
#> Loading required package: ggplot2
set.seed(40);
Location <- data.frame(Winkel = round(runif(1000, 0, 24), 0))
Location$BAD <- Location$Winkel %in% c(seq(7, 18))
Abschnitte <- c(0:24)
polar <- data.frame(Winkel2 = c(1.5, 2.34, 1.2, 3.45, 1.67, 2.61, 1.11, 13.2),
value = c(0.1, 0.03, 0.02, 0.015, 0.01, 0.04, 0.09, 0.06))
ggplot(Location, aes(x = Winkel, fill = BAD, y = (..count..)/sum(..count..))) +
geom_histogram(breaks = seq(0,24), colour = "black") +
coord_polar(start = 0) + theme_minimal() +
scale_fill_brewer(type = "seq", palette = 3) +
ylab("Percentual allocation time") +
ggtitle("") +
scale_x_continuous("", limits = c(0, 24), breaks = Abschnitte, labels = Abschnitte) +
scale_y_continuous(labels = scales::percent,
sec.axis = sec_axis(~.*5, name = "mean direction")) +
geom_segment(data = polar, aes(x = Winkel2, y = 0, xend = Winkel2, yend = value, fill = NA),
arrow = arrow(angle = 30, type = "closed", length = unit(0.3, "cm")))
#> Warning: Ignoring unknown aesthetics: fill

Resources