ggplot2: geom_bar with custom y limits [duplicate] - r

This question already has answers here:
geom_bar bars not displaying when specifying ylim
(4 answers)
Closed 17 days ago.
I want to draw a bar chart with ggplot2 along with custom y limits.
Type <- LETTERS[1:5]
Y <- c(99, 99.5, 99.0, 98.8, 98.5)
df <- data.frame(Type, Y)
The following code works fine for bar chart:
library(ggplot2)
ggplot(data = df, mapping = aes(x = Type, y = Y, fill = Type)) +
geom_bar(stat = "identity") +
theme_bw()
However, I'm not able to set the y limits. See the code below.
ggplot(data = df, mapping = aes(x = Type, y = Y, fill = Type)) +
geom_bar(stat = "identity") +
scale_y_continuous(limits = c(90, 100)) +
theme_bw()
ggplot(data = df, mapping = aes(x = Type, y = Y, fill = Type)) +
geom_bar(stat = "identity") +
ylim(90, 100) +
theme_bw()
Edited
I guess this behavior is due to stat = "identity".

Alternative, using coord_cartesian:
ggplot(data = df, mapping = aes(x = Type, y = Y, fill = Type)) +
geom_bar(stat = "identity") +
coord_cartesian(ylim = c(90, 100)) +
theme_bw()
Gives you:

Solution using geom_rect() instead of geom_bar():
# Generate data
Type <- LETTERS[1:5]
Y <- c(99, 99.5, 99.0, 98.8, 98.5)
df <- data.frame(Type, Y)
# Plot data
library(ggplot2)
ggplot() +
geom_rect(data = df,
aes(xmin = as.numeric(Type) - 0.3,
xmax = as.numeric(Type) + 0.3,
ymin = 90, ymax = Y,
fill = Type)) +
scale_x_continuous(label = df$Type, breaks = 1:nrow(df))
In geom_rect() specify x coordinates as as.numeric(X) -/+ value; ymin coordinates as wanted lower limit and ymax as actual Y values.

Related

How to smooth out a time-series geom_area with fill in ggplot?

I have the following graph and code:
Graph
ggplot(long2, aes(x = DATA, y = value, fill = variable)) + geom_area(position="fill", alpha=0.75) +
scale_y_continuous(labels = scales::comma,n.breaks = 5,breaks = waiver()) +
scale_fill_viridis_d() +
scale_x_date(date_labels = "%b/%Y",date_breaks = "6 months") +
ggtitle("Proporcions de les visites, només 9T i 9C") +
xlab("Data") + ylab("% visites") +
theme_minimal() + theme(legend.position="bottom") + guides(fill=guide_legend(title=NULL)) +
annotate("rect", fill = "white", alpha = 0.3,
xmin = as.Date.character("2020-03-16"), xmax = as.Date.character("2020-06-22"),
ymin = 0, ymax = 1)
But it has some sawtooth, how am I supposed to smooth it out?
I believe your situation is roughly analogous to the following, wherein we have missing x-positions for one group, but not the other at the same position. This causes spikes if you set position = "fill".
library(ggplot2)
x <- seq_len(100)
df <- data.frame(
x = c(x[-c(25, 75)], x[-50]),
y = c(cos(x[-c(25, 75)]), sin(x[-50])) + 5,
group = rep(c("A", "B"), c(98, 99))
)
ggplot(df, aes(x, y, fill = group)) +
geom_area(position = "fill")
To smooth out these spikes, it has been suggested to linearly interpolate the data at the missing positions.
# Find all used x-positions
ux <- unique(df$x)
# Split data by group, interpolate data groupwise
df <- lapply(split(df, df$group), function(xy) {
approxed <- approx(xy$x, xy$y, xout = ux)
data.frame(x = ux, y = approxed$y, group = xy$group[1])
})
# Recombine data
df <- do.call(rbind, df)
# Now without spikes :)
ggplot(df, aes(x, y, fill = group)) +
geom_area(position = "fill")
Created on 2022-06-17 by the reprex package (v2.0.1)
P.S. I would also have expected a red spike at x=50, but for some reason this didn't happen.

Overlaying histogram with different y-scales

I'm struggling with the following issue:
I want to plot two histograms, but since the statistics of one of the two classes is much less than the other I need to add a second y-axis to allow a direct comparison of the values.
I report below the code I used at the moment and the result.
Thank you in advance!
ggplot(data,aes(x= x ,group=class,fill=class)) + geom_histogram(position="identity",
alpha=0.5, bins = 20)+ theme_bw()
Consider the following situation where you have 800 versus 200 observations:
library(ggplot2)
df <- data.frame(
x = rnorm(1000, rep(c(1, 2), c(800, 200))),
class = rep(c("A", "B"), c(800, 200))
)
ggplot(df, aes(x, fill = class)) +
geom_histogram(bins = 20, position = "identity", alpha = 0.5,
# Note that y = stat(count) is the default behaviour
mapping = aes(y = stat(count)))
You could scale the counts for each group to a maximum of 1 by using y = stat(ncount):
ggplot(df, aes(x, fill = class)) +
geom_histogram(bins = 20, position = "identity", alpha = 0.5,
mapping = aes(y = stat(ncount)))
Alternatively, you can set y = stat(density) to have the total area integrate to 1.
ggplot(df, aes(x, fill = class)) +
geom_histogram(bins = 20, position = "identity", alpha = 0.5,
mapping = aes(y = stat(density)))
Note that after ggplot 3.3.0 stat() probably will get replaced by after_stat().
How about comparing them side by side with facets?
ggplot(data,aes(x= x ,group=class,fill=class)) +
geom_histogram(position="identity",
alpha=0.5,
bins = 20) +
theme_bw() +
facet_wrap(~class, scales = "free_y")

ggplot2 - how to limit panel and axis?

I want to know how to turn this plot:
Into this plot:
As you can see the panel and axis on the 2nd plot are limited to the data extent. I made the second graph using design software but want to know the code.
Ive already limited the x and y axis using
xlim and ylim but no difference.
Please see my code below, sorry its so messy, first time using r studio. Thanks!
ggplot() +
geom_errorbar(data = U1483_Coiling_B_M_Removed_R, mapping = aes(x = `Age (Ma) Linear Age Model`, ymin = `Lower interval*100`, ymax = `Upper interval*100`), width = 0.025, colour = 'grey') +
geom_line(data = U1483_Coiling_B_M_Removed_R, aes(x = `Age (Ma) Linear Age Model`, y = `Percent Dextral`)) +
geom_point(data = U1483_Coiling_B_M_Removed_R, aes(x = `Age (Ma) Linear Age Model`, y = `Percent Dextral`), colour = 'red') +
geom_point(data = U1483_Coiling_B_M_Removed_R, aes(x = `Age (Ma) Linear Age Model`, y = `Lab?`)) +
theme(axis.text.x=element_text(angle=90, size=10, vjust=0.5)) +
theme(axis.text.y=element_text(angle=90, size=10, vjust=0.5)) +
theme_classic() +
theme(panel.background = element_rect(colour = 'black', size = 1)) +
xlim(0, 2.85) +
ylim(0, 100)
You can use expand when specifying axis scales, like so:
# Load library
library(ggplot2)
# Set RNG
set.seed(0)
# Create dummy data
df <- data.frame(x = seq(0, 3, by = 0.1))
df$y <- 100 - abs(rnorm(nrow(df), 0, 10))
# Plot results
# Original
ggplot(df, aes(x, y)) +
geom_line() +
geom_point(colour = "#FF3300", size = 5)
# With expand
ggplot(df, aes(x, y)) +
geom_line() +
geom_point(colour = "#FF3300", size = 5) +
scale_y_continuous(expand = c(0, 0))

geom_bar ggplot2 subtract two Values

g = ggplot(Values, aes(x = X, y = Y, fill=factor(Z))) +
geom_bar(width=0.8, stat = "identity", position="dodge") +
facet_grid(Z ~ ., scale = "free_y") +
labs(x="Anno", y = "Riserva Rivalutata") +
theme(legend.position ="none") +
scale_x_continuous(breaks = seq(2000, 2070, by = 5))
d = ggplot(Values, aes(x = X, y = Y, fill=factor(Z))) +
geom_bar(width=0.8, stat = "identity", position="dodge")
p = subplot(g,d, nrows=2, shareX= T,which_layout = 1)
Hello,
I'm creating an object that when I click 2 objects Z, shows me above 2 distinct graphs, while below I would like to see the subtraction of the two.
Right now I can only see them distinct.
Can you help me to make a single chart but with only one bar given by the difference between the two data?
Thank you

Continuous position scales with no effect on the spacing between the bar and the x axis in ggplot2 with R

I am designing a bar plot with ggplot2 package.
The only problem is that I cannot get rid of the space between the bars and the x-axis.
I know that this formula should resolve the problem:
scale_y_continuous(expand = c(0, 0)) function
But it seems that the element for the error bar is overwriting it and gives always this space.
here my code:
p<-ggplot(data=tableaumergectrlmut, aes(x=ID, y=meanNSAFbait, fill=Condition)) +
geom_bar(stat="identity", position=position_dodge())+
scale_y_continuous(expand = c(0,0))+
geom_errorbar(aes(ymin=meanNSAFbait-SDNSAFbait,
ymax=meanNSAFbait+SDNSAFbait, width=0.25), position=position_dodge(.9))
Using some example data to generate a plot that (I think) shows the problem you're having.
library(ggplot2)
df <- data.frame(val = c(10, 20, 100, 5), name = LETTERS[1:4])
ggplot(df, aes(x = name, y = val, fill = name)) +
geom_bar(stat = "identity")
There is a gap from the zero point on the y axis (bottom of the bars) and where the x axis labels are.
You can remove this using scale_y_discrete or scale_y_continuous, depending on the nature of your data, and setting expand to c(0,0):
ggplot(df, aes(x = name, y = val, fill = name)) +
geom_bar(stat = "identity") +
scale_y_discrete(expand = c(0,0)) +
scale_x_discrete(expand = c(0,0))
This gives the plot:
Note I've also removed the gap along the y axis, simply remove the scale_x_discrete line to add this gap back in.
Since error bars are an issue, here are a few examples:
ggplot(df, aes(x = name, y = val, fill = name)) +
geom_bar(stat = "identity") +
geom_errorbar(aes(ymin = val - 10,
ymax = val + 10))
You can use scale to remove the padding down to the error bar:
ggplot(df, aes(x = name, y = val, fill = name)) +
geom_bar(stat = "identity") +
geom_errorbar(aes(ymin = val - 10,
ymax = val + 10)) +
scale_y_continuous(expand = c(0,0))
Or you can use coord_cartesian to give a hard cutoff:
ggplot(df, aes(x = name, y = val, fill = name)) +
geom_bar(stat = "identity") +
geom_errorbar(aes(ymin = val - 10,
ymax = val + 10)) +
scale_y_continuous(expand = c(0,0)) +
coord_cartesian(ylim = c(0, max(df$val) + 10))

Resources