I had to flip the axis of my line, but still need the geom_area to be under the curve. However I cannot figure out how to do so.
This is the line of code I tried
ggplot(PalmBeachWell, aes(x=Date, y=Depth.to.Water.Below.Land.Surface.in.ft.)) +
geom_area(position= "identity", fill='lightblue') +
theme_classic() +
geom_line(color="blue") +
scale_y_reverse()
and here is what i got
One option would be to use a geom_ribbon to fill the area above the curve which after applying scale_y_reverse will result in a fill under the curve.
Using some fake example data based on the ggplot2::economics dataset:
library(ggplot2)
PalmBeachWell <- economics[c("date", "psavert")]
names(PalmBeachWell) <- c("Date", "Depth.to.Water.Below.Land.Surface.in.ft.")
ggplot(PalmBeachWell, aes(x = Date, y = Depth.to.Water.Below.Land.Surface.in.ft.)) +
geom_ribbon(aes(ymin = Depth.to.Water.Below.Land.Surface.in.ft., ymax = Inf),
fill = "lightblue"
) +
geom_line(color = "blue") +
scale_y_reverse() +
theme_classic()
I am trying to make a grouped bar chart in which the bars are colored based on one variable(binary/ e.g. Group 1 and group2), and then the transparency of the bars are based on another value(continuous/ e.g. p-value), but I want the transparency to be specific to each groups color, and I want the gradient to and legend to be continuous.
I have been able to get close using the color, group, and fill options in geom_bar. You will see that I can get the over all gradient to work and the outlines of the bars are colored correctly. But I would like the fill to be the colors of the outlines and retain the transparency. I also tried using scale_alpha, which maps the transparencies correctly, but doesn't produce a continuous legend.
Here is a small data set like the one I am working with
## data set
d <- data.frame(ID = rep(c(123, 456), 2),
description = rep(c("cancer", "infection"), 2),
variable = c("G2", "G2", "G1", "G1"),
value = c(1.535709, 1.582127, 4.093683, 4.658328),
pvals = c(9.806872e-12, 1.160182e-09, 3.179635e-05, 1.132216e-04))
Here is the ggplot code
ggplot(d, aes(x=reorder(description, -pvals), y=value)) +
geom_bar(stat="identity", aes(col=variable, group=variable, fill=pvals), position="dodge") +
ylim(0, max(d$value) + 0.6) + xlab("") +
coord_flip() +
scale_fill_brewer(palette = "Set1",
name="",
breaks=c("G1", "G2"),
labels=c("Group 1", "Group 2")) +
scale_fill_continuous(trans = 'log10') # I am using log10 transformation because I have many small p-values and this makes the shading look better
Here is attempt 2 where the fill works but the legend does not.
ggplot(d, aes(x=reorder(description, -pvals), y=value)) +
geom_bar(stat="identity", aes(fill=variable, alpha = pvals), position="dodge") +
ylim(0, max(d$value) + 0.6) + xlab("") +
coord_flip() +
scale_fill_brewer(palette = "Set1",
name="",
breaks=c("G1", "G2"),
labels=c("G1", "G2")) +
scale_alpha(trans = "log10")
I've come up with an ugly hack, but it works so here we are. The idea is to first plot your plot as you would per usual, take the layer data and use that as input in a new plot. In this new plot, we make two layers for G1 and G2 and use the ggnewscales package to map these layers to different aesthetics. There are a few caveats I'll warn about.
First, we'll make a plot and save it as a variable:
g <- ggplot(d, aes(x=reorder(description, -pvals), y=value)) +
geom_bar(stat="identity", aes(col=variable, group=variable, fill=pvals), position="dodge") +
ylim(0, max(d$value) + 0.6) + xlab("") +
coord_flip() +
scale_fill_brewer(palette = "Set1",
name="",
breaks=c("G1", "G2"),
labels=c("Group 1", "Group 2")) +
scale_fill_continuous(trans = 'log10')
Next, we'll take the coordinates of this layers data and match them back to the original data. Note that this highly dependent on having unique y-values in your original plot, but I suppose you could also figure this out in other ways.
ld <- layer_data(g)
ld <- ld[, c("xmin", "xmax", "ymin", "ymax")]
# Match back to original data
matches <- match(ld$ymax, d$value)
# Supplement with original data
ld$pvals <- log10(d$pvals[matches])
ld$descr <- d$description[matches]
ld$vars <- d$variable[matches]
Now we'll make a new plot with geom_rects as layers, separated by the vars. In between these layers, we the first fill scale for G1 and use the new_scale_fill() afterwards. Afterwards, we'll do the second geom_rect() and the second fill scale. Then we'll muddle around with the x-axis to have it resemble the original plot somewhat.
library(ggnewscale)
ggplot(mapping = aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax)) +
geom_rect(data = ld[ld$vars == "G1", ], aes(fill = pvals)) +
scale_fill_gradient(low = "red", high = "transparent",
limits = c(min(ld$pvals), 0),
name = "Log10 P-values G1") +
new_scale_fill() +
geom_rect(data = ld[ld$vars == "G2", ], aes(fill = pvals)) +
scale_fill_gradient(low = "blue", high = "transparent",
limits = c(min(ld$pvals), 0),
name = "Log10 P-values G2") +
scale_x_continuous(breaks = seq_along(unique(d$description)),
labels = c("cancer", "infection")) +
coord_flip()
And that's the ugly hack. I might have the x-axis labels wrong, but I've found no elegant way to automatically reproduce the x-axis labels without the code getting too long.
Note: ggnewscales is known to throw errors in older versions of R, but if you use the github version they've fixed that error.
To make the script less verbose and the output is shown below if that is what you're after.
library(ggplot2)
base <- ggplot(d, aes(reorder(description, -pvals), value)) + geom_bar(stat = "identity", aes(col=variable, group=variable, fill=pvals), position = "dodge")
base_axes_flip <- base + ylim(0, max(d$value) + 0.6) + xlab("") + coord_flip()
bax_color <- base_axes_flip + scale_color_manual(values=c('#800020','#00FFFF'),
name="",
breaks=c("G1", "G2"),
labels=c("Group 1", "Group 2"))
# Note here the scale_color_manual
bax_color + scale_fill_continuous(trans = 'log10')
This produces the following output and hope it helps.
I am actually trying to do a graph with ggplot2 but I'd like to add some options (colors, legend...).
Here is my code :
ggplot(FINAL, aes(x = as.factor(gender), y=overtreatment)) +
stat_summary(fun.y="mean", geom="bar") +
facet_grid(. ~ treatment) +
theme_grey() +
xlab("Treatment") +
ylab("OT") +
scale_fill_grey() +
theme(strip.background = element_rect(colour = "black", fill = "white"))
And here the actual output.
Could you please indicate me how to change the name of 1 and 2 (without changing in it the dataframe) and how to add colours to this ?
I tried this
ggplot(FINAL, aes(x = as.factor(gender), y=overtreatment, colour=Treatment))
But it applies the color only to the outline of the figure.
To change the color of the bars you need fill = Treatment.
To change the labels on the x axis you need scale_x_discrete(labels = your_labels). See here.
So your code will look like:
ggplot(FINAL, aes(x = as.factor(gender), y=overtreatment, fill= Treatment)) +
scale_x_discrete(labels = your_labels) +
...
Below code works well and it labels the barplot correctly, However, if I try geom_text for a histogram I fail since geom_text requires a y-component and a histogram's y component is not part of the original data.
Label an "ordinary" bar plot (geom_bar(stat = "identity") works well:
ggplot(csub, aes(x = Year, y = Anomaly10y, fill = pos)) +
geom_bar(stat = "identity", position = "identity") +
geom_text(aes(label = Anomaly10y,vjust=1.5))
My Problem: How to get the correct y and label (indicated by ?) for geom_text, to put labels on top of the histogram bars
ggplot(csub,aes(x = Anomaly10y)) +
geom_histogram()
geom_text(aes(label = ?, vjust = 1.5))
geom_text requires x, y and labels. However, y and labels are not in the original data, but generated by the geom_histogram function. How can I extract the necessary data to position labels on a histogram?
geom_histogram() is just a fancy wrapper to stat_bin so you can all that yourself with the bars and text that you like. Here's an example
#sample data
set.seed(15)
csub<-data.frame(Anomaly10y = rpois(50,5))
And then we plot it with
ggplot(csub,aes(x=Anomaly10y)) +
stat_bin(binwidth=1) + ylim(c(0, 12)) +
stat_bin(binwidth=1, geom="text", aes(label=..count..), vjust=-1.5)
to get
Ok to make it aesthetically appealing here is the solution:
set.seed(15)
csub <- data.frame(Anomaly10y = rpois(50, 5))
Now Plot it
csub %>%
ggplot(aes(Anomaly10y)) +
geom_histogram(binwidth=1) +
stat_bin(binwidth=1, geom='text', color='white', aes(label=..count..),
position=position_stack(vjust = 0.5))
resultant plot will be
Below code works well and it labels the barplot correctly, However, if I try geom_text for a histogram I fail since geom_text requires a y-component and a histogram's y component is not part of the original data.
Label an "ordinary" bar plot (geom_bar(stat = "identity") works well:
ggplot(csub, aes(x = Year, y = Anomaly10y, fill = pos)) +
geom_bar(stat = "identity", position = "identity") +
geom_text(aes(label = Anomaly10y,vjust=1.5))
My Problem: How to get the correct y and label (indicated by ?) for geom_text, to put labels on top of the histogram bars
ggplot(csub,aes(x = Anomaly10y)) +
geom_histogram()
geom_text(aes(label = ?, vjust = 1.5))
geom_text requires x, y and labels. However, y and labels are not in the original data, but generated by the geom_histogram function. How can I extract the necessary data to position labels on a histogram?
geom_histogram() is just a fancy wrapper to stat_bin so you can all that yourself with the bars and text that you like. Here's an example
#sample data
set.seed(15)
csub<-data.frame(Anomaly10y = rpois(50,5))
And then we plot it with
ggplot(csub,aes(x=Anomaly10y)) +
stat_bin(binwidth=1) + ylim(c(0, 12)) +
stat_bin(binwidth=1, geom="text", aes(label=..count..), vjust=-1.5)
to get
Ok to make it aesthetically appealing here is the solution:
set.seed(15)
csub <- data.frame(Anomaly10y = rpois(50, 5))
Now Plot it
csub %>%
ggplot(aes(Anomaly10y)) +
geom_histogram(binwidth=1) +
stat_bin(binwidth=1, geom='text', color='white', aes(label=..count..),
position=position_stack(vjust = 0.5))
resultant plot will be