I am trying to determine how to ensure that the fill of a geom_rect in ggplot2 is respected once wrapped in plotly::ggplotly().
Example:
I first create a data.frame that contains the values I'll use to generate my plot.
library(ggplot2)
library(plotly)
dat <- data.frame(provider = rep(c('a','b','c'),2),
category = c(rep(c('Inpatient'),3),rep(c('Outpatient'),3)),
revenue = runif(6,100,500),
background_col = rep(c('red','green','blue'),2)
)
Using just ggplot the background panel colors on the geom_rect are respected
ggplot(dat,aes(x=category,y=revenue)) +
geom_rect(data = dat,aes(fill = background_col),xmin = -Inf,xmax = Inf,
ymin = -Inf,ymax = Inf,alpha = 0.1) +
geom_bar(stat = 'identity') +
facet_grid(~provider)
But, when I wrap it with ggplotly, those background colors disappear.
ggplotly(ggplot(dat,aes(x=category,y=revenue)) +
geom_rect(data = dat,aes(fill = background_col),xmin = -Inf,xmax = Inf,
ymin = -Inf,ymax = Inf,alpha = 0.1) +
geom_bar(stat = 'identity') +
facet_grid(~provider))
Any thoughts? I'm not super familiar with all the intricacies of plotly, so any insights are helpful!
Not sure how to get this automatically, but one workaround that ggplotly bug is to use specific numbers in place of -Inf and Inf:
ggplotly(ggplot(dat,aes(x=category,y=revenue)) +
geom_rect(data = dat,aes(fill = background_col),xmin = 0,xmax = 3,
ymin = -25,ymax = 475,alpha = 0.1) +
geom_bar(stat = 'identity') +
facet_grid(~provider))
Related
I want to create a plot that has point data (with error bars) from one data frame, and point data (coloured by gradient) from another. I can't seem to combine these plots and wondered if anyone had any suggestions. Plots are as follows:
mean_data<-data.frame(mean.x=c(1,2,3),mean.y=c(5,3,4),SE.y=c(-0.1,-0.15,-0.12),SE.x=c(-0.1,-0.15,-0.12))
x<-runif(15,min=0.1,max=5)
y<-runif(15,2,6)
grad<-1:15
point_data<-data.frame(x,y,grad)
ggplot(point_data,aes(x,y,colour=grad))+
geom_point(size=4)+
theme_classic()
ggplot(mean_data,aes(mean.x,mean.y))+
geom_point(size=3)+
geom_errorbar(aes(ymin = mean.y-SE.y, ymax = mean.y+SE.y),
position = position_dodge(0.3), width = 0.05)+
geom_errorbar(aes(xmin = mean.x-SE.x, xmax = mean.x+SE.x),
position = position_dodge(0.3), width = 0.05)+
theme_classic()
Plots are as follows:
Thanks!
You can combine them by using each dataframe to the corresponding geom and using mapping like this:
mean_data<-data.frame(mean.x=c(1,2,3),mean.y=c(5,3,4),SE.y=c(-0.1,-0.15,-0.12),SE.x=c(-0.1,-0.15,-0.12))
x<-runif(15,min=0.1,max=5)
y<-runif(15,2,6)
grad<-1:15
point_data<-data.frame(x,y,grad)
library(ggplot2)
ggplot() +
geom_point(point_data, mapping = aes(x,y,colour=grad), size = 4) +
geom_point(mean_data, mapping = aes(mean.x,mean.y), size = 3) +
geom_errorbar(mean_data, mapping = aes(x = mean.x, y = mean.y,
ymin = mean.y-SE.y, ymax = mean.y+SE.y), position = position_dodge(0.3), width = 0.05) +
geom_errorbar(mean_data, mapping = aes(x = mean.x, y = mean.y,
xmin = mean.x-SE.x, xmax = mean.x+SE.x), position = position_dodge(0.3), width = 0.05) +
theme_classic()
Created on 2022-08-15 by the reprex package (v2.0.1)
I want to shade part of the background in each facet of a simple plot. If I omit faceting and run geom_rect + geom_point, the expected results appear as shown in the MRE below. If I omit the rectangle and run geom_point + facet_grid, the expected 4 panels have each point in the correct facet. But when I combine geom_rect + geom_point + and facet_grid, the points in the first category and only those get plotted in every facet. What is going on please???
library(ggplot2)
set.seed(42)
syn.dat <- data.frame(
category.1 = as.factor(rep(c("1A", "1B"), each = 8)),
category.2 = as.factor(rep(rep(c("2A", "2B"), times = 2), each = 4)),
x = rep(-1:2, each = 4) + runif(8, max = .4),
y = rep(-1:2, each = 4) + runif(8, max = .4))
ggplot() +
geom_rect(aes(xmin = -Inf, xmax = Inf, ymin = .5,
ymax = Inf), fill = "lightyellow") +
geom_point(data = syn.dat, aes(x = x, y = y)) +
facet_grid(cols = vars(category.1),
rows = vars(category.2))
I'm not totally sure about this, but it may be that you need to explicitly provide the data argument to ggplot itself, in order for facet_grid to correctly pick up all the values?
ggplot(syn.dat) +
geom_rect(aes(xmin = -Inf, xmax = Inf, ymin = 0.5, ymax = Inf), fill = "lightyellow") +
geom_point(aes(x = x, y = y)) +
facet_grid(rows = vars(category.2), vars(cols = category.1))
I'm trying to control the color of two separate calls to geom_crosbar, using green for the first plot, and blue for the second plot. However, I get the warning from the second geom_crossbar call Scale for 'fill' is already present:
Warning: Adding another scale for 'fill', which will replace the existing
scale.
Here's an example of my code:
my.data %>%
ggplot(aes(site, npp_nofert)) +
geom_crossbar(aes(ymin=npp_nofert-npp.sd_nofert,ymax=npp_nofert+npp.sd_nofert,
fatten=1.0,fill=period),position='dodge', alpha=0.5) +
scale_fill_brewer(palette="Greens") +
#labs(y=expression(paste("MMM %",Delta," (+/- 1",sigma,")")), x="", fill="", title="") + theme_bw() +
labs(y="",x="", fill="", title="") + theme_bw() +
theme(legend.key.size=unit(1.0,"cm"),legend.direction="horizontal",legend.position=c(0.3,0.05),
axis.text.x=element_blank(),axis.ticks.x=element_blank(),
plot.title=element_text(size=12,margin=margin(t=5,b=-20)), legend.spacing=unit(0,"cm"),
text = element_text(size=15)) +
new_scale_fill() +
geom_crossbar(aes(ymin=npp_fert-npp.sd_fert,ymax=npp_fert+npp.sd_fert, fatten=1.0,fill=period),
position='dodge',alpha=0.5) +
scale_fill_brewer(palette="Blues")
And example output:
Unfortunately, I cannot dput() the data as I do not have permission to do that.
How can I set the first plot to green and second to blue? Also, just noticed the call to alpha is in the legend. How to remove that?
Notes: The 1980 to 1999 period, there is only a single plot (i.e., no treatment), so there will not be overlaying plots for that period. The x axis represents study sites, I can fix the labels later.
The general way to go about this would be to use the ggnewscale package, which allows you to 'reset' an aesthetic at some point in the plotting process.
Since there is no data to use, I'll make up some dummy data that has a vague semblance to what you're showing above.
library(ggplot2)
library(ggnewscale)
df <- data.frame(
x = 1:5,
blue_low = 1:5,
blue_mid = 2:6,
blue_high = 3:7,
green_low = 0:4,
green_mid = 2:6,
green_high = 4:8
)
ggplot(df, aes(x = 1, group = x)) +
geom_crossbar(aes(ymin = green_low, y = green_mid, ymax = green_high,
fill = as.factor(x)),
position = "dodge", alpha = 0.5) +
scale_fill_brewer(palette = "Greens") +
new_scale_fill() + # Important to put this after you defined the first scale
geom_crossbar(aes(ymin = blue_low, y = blue_mid, ymax = blue_high,
fill = paste0(x, "_blue")), # paste to differentiate scale
position = "dodge", alpha = 0.5) +
scale_fill_brewer(palette = "Blues")
Created on 2020-06-18 by the reprex package (v0.3.0)
I'm sure it won't be too difficult to take the new_scale_fill() and put it in the correct position in your plotting code, which I think is after scale_fill_brewer(palette="Greens").
So I've decided that the approach I was using for the plot looks terrible. A better solution, IMO, is to use geom_crossbar with geom_pointrange.
Here's an example using the data that teubrand provided:
library(ggplot2)
library(ggnewscale)
df <- data.frame(
x = 1:5,
blue_low = 1:5,
blue_mid = 2:6,
blue_high = 3:7,
green_low = 0:4,
green_mid = 2:6,
green_high = 4:8
)
ggplot(df, aes(x = 1, group = x)) +
geom_crossbar(aes(ymin = green_low, y = green_mid, ymax = green_high,
fill = as.factor(x)),
position = "dodge", alpha = 0.8) +
scale_fill_brewer(palette = "Greens") +
new_scale_fill() + # Important to put this after you defined the first scale
geom_pointrange(aes(ymin = blue_low, y = blue_mid, ymax = blue_high,
fill = as.factor(x)), # paste to differentiate scale
position = position_dodge(width=0.9), color="gray30") +
scale_fill_brewer(palette = "Blues")
I've been trying to plot manually labelled significance bars for a subset of groups on a ggplot2 barplot using ggsignif or ggpubr without much luck. The data is something like the following MWE:
set.seed(3)
## create data
df <- data.frame(activity = rep(c("Flying", "Jumping"), 3),
mean = rep(rnorm(6, 50, 25)),
group = c(rep("Ecuador", 2),
rep("Peru", 2),
rep("Brazil", 2)))
## plot it
ggplot(df, aes(x = activity, y = mean, fill = group)) +
geom_bar(position = position_dodge(0.9), stat = "identity",
width = 0.9, colour = "black", size = 0.1) +
xlab("Activity") + ylab("Mean")
Where I'd like to manually specify significance labels, say between Brazil/Ecuador" on "Flying", and Ecuador/Peru on "Jumping". Does anyone know how to properly deal with this kind of data, for example with ggsignif? And is there a way to refer to each bar by name, rather than try to work out its x-axis position?
If you know on which barchart you want to add your significance labels, you can do:
library(ggsignif)
library(ggplot2)
ggplot(df, aes(x = activity, y = mean, fill = group)) +
geom_bar(position = position_dodge(0.9), stat = "identity",
width = 0.9, colour = "black", size = 0.1) +
xlab("Activity") + ylab("Mean")+
geom_signif(y_position = c(60,50), xmin = c(0.7,2), xmax = c(1,2.3),
annotation=c("**", "***"), tip_length=0)
Does it answer your question ?
I'm trying to put together a ggplotly graph with three elements (geom_point, geom_line, and geom_rect) and it looks fine in ggplot2. However, when I convert to ggplotly, the geom_rect disappears. I'm thinking it's something with the inherit.aes function?
The code to build the test data is below.
library(ggplot2)
library(plotly)
dates_seq = seq.Date(as.Date("2019-03-13"), as.Date("2019-04-21"), by = "1 day")
df = data.frame(ds = dates_seq,
y = rnorm(length(dates_seq), mean = 50, sd = 5),
yhat = rnorm(length(dates_seq), mean = 50, sd = 5)
)
df$yhat_lower = df$yhat - 5
df$yhat_upper = df$yhat + 5
gg <- ggplot(df, aes(x = ds, y = y)) +
labs(x = 'Date', y = 'Sales') +
geom_ribbon(aes(ymin = yhat_lower, ymax = yhat_upper), fill = 'blue',
alpha = 0.2,
na.rm = TRUE)
start_date = as.Date("2019-04-19")
gg <- gg +
geom_point(na.rm=TRUE) +
geom_vline(xintercept = as.numeric(as.Date(start_date - lubridate::days(1))), linetype = 2, color = "black") +
geom_line(aes(y = yhat), color = 'blue',
na.rm = TRUE) +
theme_classic()
promo_df = data.frame(xmin = c("2019-03-15", "2019-04-01"), xmax = c("2019-03-18", "2019-04-08"),
ymin = -Inf, ymax = Inf, Promo = "Yes")
promo_df$id = 1:nrow(promo_df)
gg = gg +
geom_rect(data=promo_df, inherit.aes=FALSE,
aes(xmin=as.Date(xmin),
xmax=as.Date(xmax),
ymin=ymin,ymax=ymax,
group=id, fill = factor(Promo)), alpha=0.2) +
scale_fill_discrete(name = "On Promo?")
The ggplot image shows the desired output with the geom_rect.
gg
And now the ggplotly version:
ggplotly(gg)
Is there any way to get the ggplotly image to look like the basic ggplot2 chart?
Clara is right with respect to ggplotly's inability to support the ymin/max parameters. The best work around is to just manually set the parameters equal to the scale of your previous (main) layer. So in this case, it would be equal to 0/65.