Combining Bar and Line chart (double axis) in ggplot2
First, scale Rate
by Rate*max(df$Response)
and modify the 0.9
scale of Response text.
Second, include a second axis via scale_y_continuous(sec.axis=...)
:
ggplot(df) +
geom_bar(aes(x=Year, y=Response),stat="identity", fill="tan1", colour="sienna3")+
geom_line(aes(x=Year, y=Rate*max(df$Response)),stat="identity")+
geom_text(aes(label=Rate, x=Year, y=Rate*max(df$Response)), colour="black")+
geom_text(aes(label=Response, x=Year, y=0.95*Response), colour="black")+
scale_y_continuous(sec.axis = sec_axis(~./max(df$Response)))
Which yields:
How to plot a combined bar and line plot in ggplot2
Is this what you had in mind?
ratio <- max(feat$Count)/max(feat$CI2)
ggplot(feat) +
geom_bar(aes(x=Feat, y=Count),stat="identity", fill = "steelblue") +
geom_line(aes(x=Feat, y=OR*ratio),stat="identity", group = 1) +
geom_point(aes(x=Feat, y=OR*ratio)) +
geom_errorbar(aes(x=Feat, ymin=CI1*ratio, ymax=CI2*ratio), width=.1, colour="orange",
position = position_dodge(0.05)) +
scale_y_continuous("Count", sec.axis = sec_axis(~ . / ratio, name = "Odds Ratio"))
Edit: Just for fun with the legend too.
ggplot(feat) +
geom_bar(aes(x=Feat, y=Count, fill = "Count"),stat="identity") + scale_fill_manual(values="steelblue") +
geom_line(aes(x=Feat, y=OR*ratio, color = "Odds Ratio"),stat="identity", group = 1) + scale_color_manual(values="orange") +
geom_point(aes(x=Feat, y=OR*ratio)) +
geom_errorbar(aes(x=Feat, ymin=CI1*ratio, ymax=CI2*ratio), width=.1, colour="orange",
position = position_dodge(0.05)) +
scale_y_continuous("Count", sec.axis = sec_axis(~ . / ratio, name = "Odds Ratio")) +
theme(legend.key=element_blank(), legend.title=element_blank(), legend.box="horizontal",legend.position = "bottom")
Since you asked about adding p values for comparisons in the comments, here is a way you can do that. Unfortunately, because you don't really want to add **all* the comparisons, there's a little bit of hard coding to do.
library(ggplot2)
library(ggsignif)
ggplot(feat,aes(x=Feat, y=Count)) +
geom_bar(aes(fill = "Count"),stat="identity") + scale_fill_manual(values="steelblue") +
geom_line(aes(x=Feat, y=OR*ratio, color = "Odds Ratio"),stat="identity", group = 1) + scale_color_manual(values="orange") +
geom_point(aes(x=Feat, y=OR*ratio)) +
geom_errorbar(aes(x=Feat, ymin=CI1*ratio, ymax=CI2*ratio), width=.1, colour="orange",
position = position_dodge(0.05)) +
scale_y_continuous("Count", sec.axis = sec_axis(~ . / ratio, name = "Odds Ratio")) +
theme(legend.key=element_blank(), legend.title=element_blank(), legend.box="horizontal",legend.position = "bottom") +
geom_signif(comparisons = list(c("A","H"),c("B","F"),c("D","E")),
y_position = c(150,60,40),
annotation = c("***","***","n.s."))
Plot line and bar graph (with secondary axis for line graph) using ggplot
ggplot is a "high-level" plotting library, meaning that it is built to express clear relationships in data, rather than a simple system for drawing shapes. One of its fundamental assumptions is that secondary or dual data axes are usually a bad idea; such figures plot more than one relationship into the same space, with no guarantee that the two axes actually share a meaningful relationship (see for example spurious correlations).
All that said, ggplot does indeed have the ability to define secondary axes, although using it for the purpose you describe is intentionally difficult. One way to accomplish your goal would be to split your data set into two separate ones, then plot these in the same ggplot object. It's certainly possible, but take note of how much extra code is required to produce the effect you're after.
library(tidyverse)
library(scales)
df.base <- df[c('MONTHS', 'BASE')] %>%
mutate(MONTHS = factor(MONTHS, MONTHS, ordered = T))
df.percent <- df[c('MONTHS', 'INTERNETPERCENTAGE', 'SMARTPHONEPERCENTAGE')] %>%
gather(variable, value, -MONTHS)
g <- ggplot(data = df.base, aes(x = MONTHS, y = BASE)) +
geom_col(aes(fill = 'BASE')) +
geom_line(data = df.percent, aes(x = MONTHS, y = value / 40 * 12500000 + 33500000, color = variable, group = variable)) +
geom_point(data = df.percent, aes(x = MONTHS, y = value / 40 * 12500000 + 33500000, color = variable)) +
geom_label(data = df.percent, aes(x = MONTHS, y = value / 40 * 12500000 + 33500000, fill = variable, label = sprintf('%i%%', value)), color = 'white', vjust = 1.6, size = 4) +
scale_y_continuous(sec.axis = sec_axis(~(. - 33500000) / 12500000 * 40, name = 'PERCENT'), labels = comma) +
scale_fill_manual(values = c('lightblue', 'red', 'darkgreen')) +
scale_color_manual(values = c('red', 'darkgreen')) +
coord_cartesian(ylim = c(33500000, 45500000)) +
labs(fill = NULL, color = NULL) +
theme_minimal()
print(g)
ggplot2 (Barplot + LinePlot) - Dual Y axis
ggplot2
supports dual axis (for good or for worse), where the second axis is a linear transformation of the main axis.
We can work it out for this case:
library(ggplot2)
ggplot(df, aes(x = TimesReshop)) +
geom_col(aes( y = OccuranceCT, fill="redfill")) +
geom_text(aes(y = OccuranceCT, label = OccuranceCT), fontface = "bold", vjust = 1.4, color = "black", size = 4) +
geom_line(aes(y = AverageRepair_HrsPerCar * 1500, group = 1, color = 'blackline')) +
geom_text(aes(y = AverageRepair_HrsPerCar * 1500, label = round(AverageRepair_HrsPerCar, 2)), vjust = 1.4, color = "black", size = 3) +
scale_y_continuous(sec.axis = sec_axis(trans = ~ . / 1500)) +
scale_fill_manual('', labels = 'Occurance', values = "#C00000") +
scale_color_manual('', labels = 'Time Reshop', values = 'black') +
theme_minimal()
R - creating a bar and line on same chart, how to add a second y axis
Starting with version 2.2.0 of ggplot2
, it is possible to add a secondary axis - see this detailed demo. Also, some already answered questions with this approach: here, here, here or here. An interesting discussion about adding a second OY axis here.
The main idea is that one needs to apply a transformation for the second OY axis. In the example below, the transformation factor is the ratio between the max values of each OY axis.
# Prepare data
library(ggplot2)
set.seed(2018)
df <- data.frame(x = c(1:5), y = abs(rnorm(5)*100))
df$y2 <- abs(rnorm(5))
# The transformation factor
transf_fact <- max(df$y)/max(df$y2)
# Plot
ggplot(data = df,
mapping = aes(x = as.factor(x),
y = y)) +
geom_col(fill = 'blue') +
# Apply the factor on values appearing on second OY axis
geom_line(aes(y = transf_fact * y2), group = 1) +
# Add second OY axis; note the transformation back (division)
scale_y_continuous(sec.axis = sec_axis(trans = ~ . / transf_fact,
name = "Second axis")) +
geom_label(aes(y = transf_fact * y2,
label = round(y2, 2))) +
theme_bw() +
theme(axis.text.x = element_text(angle = 20, hjust = 1))
But if you have a particular wish for the one-to-one transformation, like, say value 100 from Y1 should correspond to value 1 from Y2 (200 to 2 and so on), then change the transformation (multiplication) factor to 100 (100/1): transf_fact <- 100/1
and you get this:
The advantage of transf_fact <- max(df$y)/max(df$y2)
is using the plotting area in a optimum way when using two different scales - try something like transf_fact <- 1000/1
and I think you'll get the idea.
ggplot bar plot by multiple groups + line graph
You could use facet_wrap to plot the weeks beside each other:
ggplot(data, aes(fill=tmp)) +
geom_bar(aes(x=day_s, y=mpd, group=tmp) ,stat="identity") +
facet_wrap(.~tmp) +
theme_bw()
Update
To get summed up rpd as line plot you can do the following:
library(dplyr)
rpd_sum <- data %>%
group_by(tmp, day_s) %>%
summarise(sum_rpd = sum(rpd)) %>%
mutate(newClass = paste(tmp, day_s))
data$newClass <- paste(data$tmp, data$day_s)
dataNew <- merge(data, rpd_sum )
ggplot(dataNew, aes(fill=tmp)) +
geom_bar(aes(x=day_s, y=mpd) ,stat="identity") +
geom_line(aes(x=day_s, y=sum_rpd*10, group=tmp),stat="identity") +
scale_y_continuous(sec.axis = sec_axis( trans=~./10, name="rpd Axis")) +
facet_wrap(.~tmp) +
theme_bw()
ggplot with 2 y axes on each side and different scales
Sometimes a client wants two y scales. Giving them the "flawed" speech is often pointless. But I do like the ggplot2 insistence on doing things the right way. I am sure that ggplot is in fact educating the average user about proper visualization techniques.
Maybe you can use faceting and scale free to compare the two data series? - e.g. look here: https://github.com/hadley/ggplot2/wiki/Align-two-plots-on-a-page
Related Topics
Using R to List All Files with a Specified Extension
Multiplying All Elements of a Vector in R
How to Initialize Empty Data Frame (Lot of Columns at the Same Time) in R
Find the Intersection of Overlapping Ranges in Two Tables Using Data.Table Function Foverlaps
Write Many Files in a for Loop
Display Custom Image as Geom_Point
R Ggplot2 Merge with Shapefile and CSV Data to Fill Polygons
Why Do Some Unicode Characters Display in Matrices, But Not Data Frames in R
Lib Unspecified & Error in Loadnamespace
Creating a New Variable from a Lookup Table
How to Geocode a Simple Address Using Data Science Toolbox
Set Locale to System Default Utf-8