Combining two graphs with different x axis in R - r

I'm trying to combine a bar chart and line chart by using ggplot. The problem is, the x axis of bar chart is shop names while the x axis of line chart is date. Graphs look like this:
g1 <- ggplot(plot_data, aes(x=shop, y=conversion_rate)) +
geom_bar(stat="identity", position=position_dodge())
g2 <- ggplot() + geom_line(plot_data_mean, mapping = aes(x=date, y=conversion_rate_average))
Is there a way to combine these two graphs?

You can use the cowplot package to achieve this. Especially the cowplot::plot_grid() function allows for many customizations of the output plot
library(ggplot2)
library(cowplot)
p1 <- ggplot() +
geom_point(aes(x = runif(n = 10), y = runif(n = 10)))
p2 <- ggplot() +
geom_line(aes(x = runif(n = 10), y = runif(n = 10)))
p_combined <- cowplot::plot_grid(p1, p2, labels = c("A)", "B)"))

Related

How can I make stacked dot plots using a facet in GGplot2? R

I am trying to stack dot plots using a facet in GGplot2.
My first dot plot:
plot1 <- ggplot(marathon, aes(x = MarathonTime, y = first_split_percent)) +
geom_point()
plot1
My second:
plot2 <- ggplot(marathon, aes(x=MarathonTime, y=km4week)) +
geom_point()
plot2
I am trying to stack them on top of each other as they share the same x-axis. I have tried using facet_wrap as so:
plot3 <- ggplot(marathon, aes(x = MarathonTime, y = first_split_percent)) +
geom_point() +
facet_wrap(km4week~.)
plot3
I have also played around with the 'rows = vars(km4week), cols = vars(MarathonTime)' functions but have had no luck. Is there a way to achieve what I am describing without a facet? Or am I using the Facet function incorrectly? Any help is greatly appreciated!
To stack your two plots using facetting you first have to reshape your data so that your columns become categories of one column or variable which could then be used in facet_wrap.
Using some fake random example data:
set.seed(123)
marathon <- data.frame(
MarathonTime = runif(100, 2, 4),
first_split_percent = runif(100, 45, 55),
km4week= runif(100, 20, 140)
)
library(ggplot2)
library(tidyr)
marathon_long <- marathon |>
pivot_longer(c(first_split_percent, km4week), names_to = "variable")
ggplot(marathon_long, aes(x = MarathonTime, y = value)) +
geom_point() +
facet_wrap(~variable, scales = "free_y", strip.position = "right", ncol = 1)

Multipanel plot with ggplot2?

I have bar charts faceted by stock symbol name:
I would like to be able to add a little "subplot" of an indicator below each plot, like this:
Is this possible with ggplot2? I thought of a secondary axis, but most often there is no linear relation between the main plot axis and the indicator axis (so using sec_axis is not an option).
Thanks!
Since these appear to be categorically different types of plots, I think you'll have better luck creating separate plots and then rendering them together. Here's one solution using cowplot package:
library(ggplot2)
library(cowplot)
#sample data
df <- data.frame(x = 1:100, y = cumsum(rnorm(100)), volume = sample(1:10, 100, replace = TRUE))
p1 <- ggplot(df, aes(x,y)) +
geom_line()
p2 <- ggplot(df, aes(x,volume)) +
geom_bar(stat = "identity")
plot_grid(p1, p2, align = "v", ncol = 1, rel_heights = c(.8, .2))
Created on 2019-01-25 by the reprex package (v0.2.1)
Edit
Continuing to build on this kludgy example to support the concept of faceting. Ignore the ugly graph, it's smooshed due to image size constraints.
library(ggplot2)
library(cowplot)
library(gridExtra)
#sample data
df <- data.frame(x = 1:100, y = cumsum(rnorm(100)), volume = sample(1:10, 400, replace = TRUE), group = letters[1:4])
plots <- list()
for (j in unique(df$group)){
plot_df <- df[df$group == j, ]
p1 <- ggplot(plot_df, aes(x,y)) +
geom_line() +
facet_wrap(~group) +
xlab("")
p2 <- ggplot(plot_df, aes(x,volume)) +
geom_bar(stat = "identity")
p_out <- plot_grid(p1, p2, align = "v", ncol = 1, rel_heights = c(.7, .3))
plots[[j]] <- p_out
}
do.call(grid.arrange, plots)
Created on 2019-01-25 by the reprex package (v0.2.1)

Add labels above top axis in ggplot2 graph while keeping original x axis on bottom

I'm trying to add some labels to a ggplot2 boxplot to indicate the number of observations, and I'd like that annotation to appear above the top axis of the graph. I can add them inside the graph pretty easily, and I suspect there's an application of ggplot_gtable that might do this, but I don't understand how to use that (a point in the direction of a good tutorial would be much appreciated). Here's some example data with labels:
Count <- sample(100:500, 3)
MyData <- data.frame(Category = c(rep("A", Count[1]), rep("B", Count[2]),
rep("C", Count[3])),
Value = c(rnorm(Count[1], 10),
rnorm(Count[2], 20),
rnorm(Count[3], 30)))
MyCounts <- data.frame(Category = c("A", "B", "C"),
Count = Count)
MyCounts$Label <- paste("n =", MyCounts$Count)
ggplot(MyData, aes(x = Category, y = Value)) +
geom_boxplot() +
annotate("text", x = MyCounts$Category, y = 35,
label = MyCounts$Label)
What I'd love is for the "n = 441" and other labels to appear above the graph rather than just inside the upper boundary. Any suggestions?
Rather than separately calculating the counts, you can add the counts with geom_text and the original data frame (MyData). The key is that we need to add stat="count" inside geom_text so that counts will be calculated and can be used as the text labels.
theme_set(theme_classic())
ggplot(MyData, aes(x = Category, y = Value)) +
geom_boxplot() +
geom_text(stat="count", aes(label=paste0("n=",..count..)), y=1.05*max(MyData$Value)) +
expand_limits(y=1.05*max(MyData$Value))
To put the labels above the plot, add some space above the plot area for the text labels and then use the code in the answer linked by #aosmith to override clipping:
library(grid)
theme_set(theme_bw())
p = ggplot(MyData, aes(x = Category, y = Value)) +
geom_boxplot() +
geom_text(stat="count", aes(label=paste0("n=",..count..)),
y=1.06*max(MyData$Value), size=5) +
theme(plot.margin=margin(t=20))
# Override clipping
gt <- ggplot_gtable(ggplot_build(p))
gt$layout$clip[gt$layout$name == "panel"] <- "off"
grid.draw(gt)

R: Remove border when plotting with ggplot2 + ggExtra + cowplot

I couldn't find the way not to plot the outer frame when combining graphs through ggplot2 + ggExtra + cowplot. I am not sure where I have to tell R, but suspect the issue to lie in ggExtra. Here is an example:
require(ggplot2)
require(cowplot)
require(ggExtra)
# Creat a graph
A <- ggplot(mpg, aes(x = cty, y = hwy, colour = factor(cyl))) + geom_point(size = 2.5)
# Add marginal histogram
B <- ggExtra::ggMarginal(A,type = 'histogram', margins = 'x', size = 9)
# Combine through cowplot
combo <- plot_grid(B,B,labels=c("A","B"))
plot(combo) # looks fine
# Re-combine through cowplot
plot_grid(B,combo,ncol=1,rel_heights = c(2,3)) # that's where I got an unwanted nasty frame around 'combo'
Any hint would be greatly appreciated!
p <- plot_grid(B,combo,ncol=1,rel_heights = c(2,3))
p <- p + panel_border(remove = TRUE)
https://rdrr.io/cran/cowplot/man/panel_border.html

Align discrete and continuous axes with ggplot2 and grid

I'm attempting to display a grid figure of summarized weekly data of several variables. The two components of this graph that are most pertinent are a distributional summary graph (so box plot or violin plot) of the values that a certain variables took over a given week and a cumulative count graph of an integer variable accumulating over weeks (so a step plot). I would like to plot these two graphs in on an aligned x-axis using grid. I'll be using ggplot2 to make the individual graphs, because I've got a crush on Hadley Wickham (j/k, ggplot is just really, really nice).
The problem is that geom_boxplot only takes factors for x-axis and the geom_step only takes continuous data for the x-axis. These don't necessarily align even if you force similar x-limits with coord_cartesian or scale_x_....
I've cobbled together a hack using geom_rect that will work for this specific application, but that will be a pain to adapt if, for example, I have some other factor that results in multiple boxes for a single week.
The obligatory reproducible:
library(ggplot2)
library(grid)
var1 <- data.frame(val = rnorm(300),
week = c(rep(25, 100),
rep(26, 100),
rep(27, 100))
)
var2 <- data.frame(cumul = cumsum(c(0, rpois(2, 15))),
week = c(25, 26, 27)
)
g1 <- ggplot(var1, aes(x = factor(week), y = val)) +
geom_boxplot()
g2 <- ggplot(var2, aes(x = week, y = cumul)) +
geom_step() + scale_x_continuous(breaks = 25:27)
grid.newpage()
grid.draw(rbind(ggplotGrob(g1),
ggplotGrob(g2),
size = "last"))
And the kludge:
library(dplyr)
chiggity_check <- var1 %>%
group_by(week) %>%
summarise(week.avg = mean(val),
week.25 = quantile(val)[2],
week.75 = quantile(val)[4],
week.05 = quantile(val)[1],
week.95 = quantile(val)[5])
riggity_rect <- ggplot(chiggity_check) +
geom_rect(aes(xmin = week - 0.25, xmax = week + 0.25,
ymin = week.25,
ymax = week.75)) +
geom_segment(aes(x = week - 0.25, xend = week + 0.25,
y = week.avg, yend=week.avg),
color = "white") +
geom_segment(aes(x = week, xend = week ,
y = week.25, yend=week.05)) +
geom_segment(aes(x = week, xend = week ,
y = week.75, yend=week.95)) +
coord_cartesian(c(24.5,27.5)) +
scale_x_continuous(breaks = 25:27)
grid.newpage()
grid.draw(rbind(ggplotGrob(riggity_rect),
ggplotGrob(g2 + coord_cartesian(c(24.5,27.5))),
size = "last"))
So the question(s) is/are: is there a way to force geom_boxplot to a continuous axis or geom_step to a factor axis? Or is there some other implementation, perhaps stat_summary that will be a bit more flexible so that I can align axes and also potentially easily add in things like grouping color variables?
One approach is to plot the two charts on an x-axis set up with factor(week), but in the g2 plot (the step plot) do so in geom_blank() so that the scale is set up. Then in geom_step(), plot on a numeric scale: as.numeric(factor(week))
library(ggplot2)
library(grid)
# Your data
var1 <- data.frame(val = rnorm(300),
week = c(rep(25, 100),
rep(26, 100),
rep(27, 100))
)
var2 <- data.frame(cumul = cumsum(c(0, rpois(2, 15))),
week = c(25, 26, 27)
)
# Your g1
g1 <- ggplot(var1, aes(x = factor(week), y = val)) +
geom_boxplot()
# Modified g2
g2 <- ggplot(var2) + geom_blank(aes(x = factor(week), y = cumul)) +
geom_step(aes(x = as.numeric(as.factor(week)), y = cumul))
grid.newpage()
grid.draw(gridExtra::rbind.gtable(ggplotGrob(g1),
ggplotGrob(g2),
size = "last"))

Resources