How to Use Geom_Rect with Discrete Axis Values

how do I use geom_rect with discrete axis values

You can try:

ggplot(data = df) +
geom_rect(data = df, aes(x = x, y=y), xmin = as.numeric(df$x[[2]]) - 0.3,
xmax = as.numeric(df$x[[3]]) + 0.3,
ymin = 0, ymax = 2)

This works, as if you call xmin and xmax etc outside of the aes call, you can use whatever you want. The factor levels are used in the plot to plot them out, so as.numeric will make sure you get the right one.

Widen geom_rect()-rectangle in ggplot2 on discrete scale

Just set xmin and xmax to -Inf and Inf respectively.

exp %>%
ggplot(aes(b,a)) +
geom_rect(aes(xmin=-Inf,xmax=Inf,ymin=0,ymax=50,fill="red"))+
geom_point()

Sample Image

plotting rectangles and lineranges with discrete axis in ggplot2

You can also use geom_tile in place of geom_rect:

ggplot(mydat, aes(est, mylvl)) + 
geom_tile(aes(width = ciup-cilow, height=0.1), fill="red", color="black") +
geom_point() +
facet_grid(mytrt ~ mymsmt, scales = "free")

Sample Image

ggplot2 geom_rect plot quartiles stacked with data point and discrete x-axis

Here are two possible approaches, depending on your needs. In either case, though, I think geom_col would be easier. (It's possible to use geom_rect when your x-axis data is discrete, but it's not the most straightforward. Example)

Sample data (I switched Q3 & Q4 values for Lab as Q3's value was larger, which didn't make sense):

msr_type <- c('Clinic','Hospital','Lab','Office')
result <- c(10.5, 21.9, 30.5, 14.5)
sec_q <- c(9.5, 15.2, 25, 9)
third_q <- c(11, 17, 29, 20)
four_q <- c(17, 25, 34, 25)
df_check <- data.frame(msr_type, result, sec_q, third_q, four_q)

Approach 1 (keeping the wide format of the original dataset):

ggplot(df_check,
aes(x = msr_type)) +
geom_col(aes(y = four_q), fill = "slategray3") +
geom_col(aes(y = third_q), fill = "slategray2") +
geom_col(aes(y = sec_q), fill = "slategray1") +
geom_point(aes(y = result)) +
xlab("") + ylab("")

Since Q2 <= Q3 <= Q4, you can simply create one set of bars for each quartile & overlay them. But if you need a legend for Q2 / Q3 / Q4, it's not that straightforward...

Approach 1

Approach 2 (converting the dataset to long format so that all the quartile values are in the same variable):

df_check2 <- df_check %>%
tidyr::gather(quartile, quartile.value, -msr_type, -result) %>%
mutate(quartile = factor(quartile, levels = c("sec_q", "third_q", "four_q")))

ggplot(df_check2,
aes(x = msr_type)) +
geom_col(aes(y = quartile.value, fill = quartile),
position = position_dodge(0), width = 2.5) +
geom_point(aes(y = result)) +
scale_fill_manual(values = c("slategray1", "slategray2", "slategray3")) +
xlab("") + ylab("")

A legend is created by default using this approach. It's also more flexible if you have other quartiles / deciles / percentiles / etc to plot.

Approach 2

ymin and ymax for discrete axis in geom_area

Like Joran says, just put the geom_area data outside of aes. Logical because you aren't mapping.

m <- median(esoph$ncases)
Q1 <- quantile(as.numeric(esoph$ncases), c(0.25))
Q3 <- quantile(as.numeric(esoph$ncases), c(0.75))

ggplot(esoph, aes(x=agegp, y=ncases))+
geom_rect(xmin = -Inf , xmax = Inf , ymin = Q1 , ymax = Q3 ,fill = "blue", alpha = .002)+
geom_hline(yintercept= m,colour = "white", size=1) + geom_boxplot(aes(group=agegp))+ coord_flip() + geom_point() +
theme_classic()

Sample Image

How to get a ggplot2 function of discrete geom_rect to obey the alpha (transparency) values

I don't see a scale_alpha_identity or scale_alpha_continuous(range = c(0, 0.2)), so I suspect ggplot is mapping your various alpha values to the default range of (0.1, 1), regardless of the range of the underlying values.

Here's a short example:

library(tidyverse); library(lubridate)
my_data <- tibble(
date = seq.Date(ymd(20190101), ymd(20191231), by = "5 day"),
month = month(date),
color = case_when(month <= 2 ~ "cornflowerblue",
month <= 5 ~ "springgreen4",
month <= 8 ~ "goldenrod2",
month <= 11 ~ "orangered3",
TRUE ~ "cornflowerblue"))

my_data %>%
uncount(20, .id = "row") %>%
mutate(alpha_val = row / max(row) * 0.2) %>%
ggplot(aes(date, 5 + alpha_val * 5, fill = color, alpha = alpha_val)) +
geom_tile(color = NA) +
scale_fill_identity() +
scale_alpha_identity() +
expand_limits(y = 0) +
coord_polar() +
theme_void()

Sample Image

Using factor levels with geom_rect

I got some help after asking the same question on the comp.lang.r.general mailing list
(http://permalink.gmane.org/gmane.comp.lang.r.general/313656). I ended up adding the following:

nodelist <- sort(levels(flatdata$value))

and then using

geom_rect(aes(ymin=as.Date("8-Apr-2014", format="%d-%b-%Y"),
ymax=as.Date("30-Apr-2014", format="%d-%b-%Y"),
xmin=which(nodelist=="node004")-0.5,
xmax=which(nodelist=="node004")+0.5,
fill="red", alpha=0.25))

colour geom_rect under certain condition

OP, this should probably help you. You're trying to draw what appears to be a column or bar chart. In this case, it's probably best to use geom_col instead of geom_rect. With geom_col you only have to supply an x aesthetic (discrete value), and a y aesthetic for the height of the bar. You have not shared your data, but it seems the x axis is categorical already in your dataset, right?

Here's a reprex:

library(ggplot2)

set.seed(1234)
df <- data.frame(x=LETTERS, y=rnorm(26))

ggplot(df, aes(x,y)) +
geom_col(
aes(fill=ifelse(y>0, 'positive', 'negative')),
color='black', alpha=0.8
) +
scale_fill_manual(name='Value', values=c('positive'='orange', 'negative'='gray'))

Sample Image

What's going on here is that we only have to supply x and y to get the bars in the correct place and set the height. For the fill of each of the bars, you can actually just set the label to be "positive" or "negative" (or whatever your desired label would be) on the fly via an ifelse statement. Doing this alone will result in creating a legend automatically with fill colors chosen automatically. To fix a particular set of colors, I'm setting that manually via scale_fill_manual() and supplying a named vector to the values argument.

In your case, you can probably do something similar for geom_rect. That is, you could just try specifying fill= inside aes() and following a similar manner to here if you want... but I'd recommend switching to use geom_col, as it is most appropriate for what you're doing.

EDIT

As OP indicated in the comment, in the original question on which this is based, geom_rect is required since the bars minimum is not always the same number. The ymin aesthetic changes, so it makes sense to use geom_rect here.

The brute force way is to still use ifelse statements inside aes() for fill. It get's a bit dodgey, but it gets the job done:

ggplot(df) +
geom_rect(
aes(
xmin = char2num(sites) - 0.4,
xmax = char2num(sites) + 0.4,
ymin = ifelse(trop == "pt", 0.1, 1),
ymax = conc,
fill = ifelse(trop == "pt",
ifelse(conc > 0.1, 'positive', 'negative'),
ifelse(conc > 1, 'positive', 'negative'))
),
colour = 'black', alpha = 0.8
) +
scale_y_log10() +
# Fake discrete axis
scale_x_continuous(labels = sort(unique(df$sites)),
breaks = 1:3) +
scale_fill_manual(name='Conc', values=c('positive'='orange', 'negative'='gray')) +
facet_grid(. ~ trop) +
theme_bw()

Sample Image

To complete the setup, you may want to adjust the order of the items in the legend and avoid some of that kind of icky nested ifelse stuff. In that case, you can always do the checking outside the ggplot call. If you have more than the two values for df$trop, you can consider creating the df$conc_min column via a merge with another dataset, but it works just fine here.

df$conc_adjust <- char2num(df$sites)
df$conc_min <- ifelse(df$trop=='pt', 0.1, 1)
df$status <- ifelse(df$conc > df$conc_min, 'positive', 'negative')

# levels of the factor = the order appearing in the legend
df$status <- factor(df$status, levels=c('positive', 'negative'))

ggplot(df) +
geom_rect(
aes(
xmin = conc_adjust - 0.4,
xmax = conc_adjust + 0.4,
ymin = conc_min,
ymax = conc,
fill = status
),
colour = 'black', alpha = 0.8
) +
scale_y_log10() +
# Fake discrete axis
scale_x_continuous(labels = sort(unique(df$sites)),
breaks = 1:3) +
scale_fill_manual(name='Conc', values=c('positive'='orange', 'negative'='gray')) +
facet_grid(. ~ trop) +
theme_bw()

Sample Image

In ggplot, how to manage width of rectangle when scale is discrete?

Here I created a new column which is the numeric version of the factor column x, but then used scale_x_continuous to modify the axis such that it looks discrete.

library(ggplot2)

df <- data.frame(
x = c("a", "b", "c"),
y = c(1, 4, 2),
w = c(0.5, 1.2, 0.1)
)

df$xn <- as.numeric(df$x)

ggplot(df, aes(xmin = xn - w / 2,
xmax = xn + w / 2,
ymin = y,
ymax = y + 1,
fill = x)) +
geom_rect() +
scale_fill_discrete(guide = FALSE) +
scale_x_continuous(expand = c(0, 0.5),
labels = levels(df$x),
breaks = 1:length(levels(df$x))) +
coord_cartesian(xlim = c(1, length(levels(df$x))))

Sample Image



Related Topics



Leave a reply



Submit