ggplot2: fill color behaviour of geom_ribbon
An option that doesn't require manually creating another column would be to do the logic within aes(fill =
itself;
## fill dependent on level > level2
h +
geom_ribbon(aes(ymin = level, ymax = level2, fill = level > level2)) +
geom_line(aes(y = level)) + geom_line(aes(y=level2)) +
scale_fill_manual(values=c("red", "green"), name="fill")
Or, if you only want to fill based on that condition being true,
## fill dependent on level > level2, no fill otherwise
h +
geom_ribbon(aes(ymin = level, ymax = level2, fill = ifelse(level > level2, TRUE, NA))) +
geom_line(aes(y = level)) + geom_line(aes(y=level2)) +
scale_fill_manual(values=c("green"), name="fill")
I assume the lack of interpolated fill seems to have something to do with the ggplot2
version, as I get the same thing happening with @beetroot's code
## @beetroot's answer
huron$id <- 1:nrow(huron)
huron$group <- ifelse(huron$id <= 50, "A", "B")
h <- ggplot(huron, aes(year))
h +
geom_ribbon(aes(ymin = level, ymax = level2, fill = group)) +
geom_line(aes(y = level)) + geom_line(aes(y = level2))
I get @ManuK's image output when running that code without logic in aes(fill =
.
Custom colours for geom_ribbon fill based for categorical data
Try adding scale_fill_manual using the same colors defined in you scale_color_manual argument.
ggplot(data, aes(num, value, colour=category, fill=category)) +
scale_colour_manual(values = c("A"="black", "B"="red", "C"="magenta", "D"="green")) +
geom_smooth(method="loess", se=FALSE) +
geom_ribbon(aes(x=num, ymax=upperLoess, ymin=lowerLoess, fill=category),
alpha=0.2) +
scale_fill_manual(values = c("A"="black", "B"="red", "C"="magenta", "D"="green"))
matching colors
geom_ribbon: create a rule for colour changes using fill
When you specify something in the original ggplot()
it will be inherited by subsequent layers. Don't put group = 1
up there globally. If you need it for the line
layer, put group = 1
just in geom_line
. Similarly, don't put fill=factor(groups)
in the base ggplot()
call because you don't want it being used in the point
layer, the second ribbon
layer, etc. You only need it in the first ribbon
layer, so only put it there. (And you need to put it inside aes()
since it references a column name!)
pred_avg$DATE = as.Date(pred_avg$DATE)
# Create the plot
ggplot(pred_avg, aes(x = DATE, y = canopycover)) +
geom_point () +
geom_line(group = 1) +
geom_ribbon(
data = pred_avg,
aes(
ymin = canopycoverSDmin,
ymax = canopycoverSDmax,
fill = groups),
alpha = 0.1
) +
scale_fill_manual(values = c("red", "green"), name = "fill") +
geom_ribbon(aes(ymin = covermin, ymax = covermax), alpha = 0.1) +
scale_x_date(breaks = "1 week") +
theme_bw() + theme(
panel.border = element_blank(),
panel.grid.major = element_blank(),
axis.text = element_text(size = 10),
axis.title = element_text(size = 12),
plot.title = element_text(size = 14, face = "bold"),
legend.title = element_blank(),
axis.text.x = element_text(angle = 90, hjust = 1),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "black")
)
wrong color in geom_ribbon?
As AntoniosK said, you can use the function scale_fill_manual()
, but a second option is to put the parameter fill = 'blue'
outside of the function aes()
(same thing for the parameter alpha).
Like this :
testdf %>%
ggplot(., aes(x = time)) +
geom_line(aes(y = coef)) +
geom_ribbon(aes(ymin = low_ci, ymax = high_ci), alpha = 0.3, fill = 'blue')
Colouring geom_ribbon in ggplot2 & R
You can use scale_fill_manual()
to change fill colors. First argument is your data level and second argument is actual color.
+scale_fill_manual(values=c("green"="green","red"="red"))
Colour area above y-lim in geom_ribbon
There's really not a direct way to do this in ggplot2 as far as I know. If you didn't want the transparency, then it would be pretty easy just to draw a rectangle in the background and then draw the ribbon on top.
ggplot(df, aes(x = Variable, y = value)) +
geom_rect(aes(xmin=min(Variable), xmax=max(Variable), ymin=0, ymax=1), fill="green") +
geom_ribbon(aes(ymin=pmin(value,1), ymax=0), fill="red", col="red") +
geom_hline(aes(yintercept=0), color="black") +
theme_bw(base_size = 16) +
geom_point()
But if you need the transparency, you're going to need to calculate the bounds of that region which is messy because the points where the line crosses the axis are not in your data, you would need to calculate those. Here's a function that finds the places where the region crosses the axis and keeps track of the top points
crosses <- function(x, y) {
outx <- x[1]
outy <- max(y[1],0)
for(i in 2:length(x)) {
if (sign(y[i-1]) != sign(y[i])) {
outx <- c(outx, -y[i-1]*(x[i]-x[i-1])/(y[i]-y[i-1])+x[i-1])
outy <- c(outy, 0)
}
if (y[i]>0) {
outx <- c(outx, x[i])
outy <- c(outy, y[i])
}
}
if (y[length(y)]<0) {
outx <- c(outx, x[length(x)])
outy <- c(outy, 0)
}
data.frame(x=outx, y=outy)
}
Basically it's just doing some two-point line formula stuff to calculate the intersection.
Then use this to create a new data frame of points for the top ribbon
top_ribbon <- with(df, crosses(Variable, value))
And plot it
ggplot(df, aes(x = Variable, y = value)) +
geom_ribbon(aes(ymin=pmin(value,1), ymax=0), fill="red", col="red", alpha=0.5) +
geom_ribbon(aes(ymin=y, ymax=1, x=x), fill="green", col="green", alpha=0.5, data=top_ribbon) +
geom_hline(aes(yintercept=0), color="black") +
theme_bw(base_size = 16) +
geom_point()
Change colors of a single geom_ribbon() depending on variable
Since in ggplot
you cannot have more than one color per line, we can expand the data into multiple lines that connect to each other so they appear to be one line. Then we can assign each section a color.
To make sure they appear connected, we have to expand the data so that the start of the next group and the end of the previous group have the same x
and y
coordinates, but different groups:
library(zoo)
library(data.table)
df$group <- rleid(df$type)
df_plot <- head(do.call(rbind, by(df, df$group, rbind, NA)), -1)
df_plot[,c("group","type")] <- lapply(df_plot[,c("group","type")], na.locf)
df_plot[] <- lapply(df_plot, na.locf, fromLast = TRUE)
ggplot(df_plot, aes(x = year)) +
geom_ribbon(aes(ymin = lower, ymax = upper, fill = type, group = group))
Compare this to the original, uncolored line:
ggplot(df, aes(x = year)) +
geom_ribbon(aes(ymin = lower, ymax = upper))
One note - I lapply
with the na.locf
so the type doesnt get changed on me. I am aware you can do na.locf(df_plot)
.
Related Topics
Error in Get(As.Character(Fun), Mode = "Function", Envir = Envir)
Retain Attributes When Using Gather from Tidyr (Attributes Are Not Identical)
Extracting Zip+CSV File from Attachment W/ Image in Body of Email
Check to See If a Value Is Within a Range
\Sexpr{} Special Latex Characters ($, &, %, # etc.) in .Rnw-File
Setting Individual Y Axis Limits with Facet Wrap Not with Scales Free_Y
Unscale and Uncenter Glmer Parameters
Extract Name of Data.Frame in R as Character
How to Create a Variable of Rownames
2 Knitr/R Markdown/Rstudio Issues: Highcharts and Morris.Js
R/Gis: How to Subset a Shapefile by a Lat-Long Bounding Box
R Corpus Is Messing Up My Utf-8 Encoded Text
Why Doesn't Comparison Between Numeric and Character Variables Give a Warning
How to Colour the Labels of a Dendrogram by an Additional Factor Variable in R