In a ggplot boxplot, it is easy to use jitter to add the raw data points with varying degrees of jitter. With zero jitter the following code
dat <- data.frame(group=c('a', 'b', 'c'), values = runif(90))
ggplot(dat, aes(group, values)) +
geom_boxplot(outlier.size = 0) +
geom_jitter(position=position_jitter(width=0), aes(colour=group), alpha=0.7) +
ylim(0, 1) + stat_summary(fun.y=mean, shape=3, col='red', geom='point') +
opts(legend.position = "right") + ylab("values") + xlab("group")
produces the plot below.
Is it possible to use zero jitter but add an offset such that the points are in a line but shifted left by 25% of the box width? I tried geom_point with dodge but this generated a jitter.
If we convert group to numeric and then add an offset, you seem to get your desired output. There is probably a more effective / efficient way, but give this a whirl:
ggplot(dat, aes(group, values)) +
geom_boxplot(outlier.size = 0) +
geom_point(aes(x = as.numeric(group) + .25, colour=group), alpha=0.7) +
ylim(0, 1) + stat_summary(fun.y=mean, shape=3, col='red', geom='point') +
opts(legend.position = "right") + ylab("values") + xlab("group")
Related
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 have a grid of plots, all with the same y and x-axis scale. The plots represent time in the x-axe and mean values in the y-axe with their standard errors. My problem is that some errorbars are not entirely within the plot margins, and I wonder if there is some way to represent the part of the errorlines that are within the plot margins. Below I give a fake example and code to play with:
df <- data.frame(time=seq(-15,15,1),
mean=c(0.49,0.5,0.53,0.55,0.57,0.59,0.61,0.63,0.65,0.67,0.69,0.71,0.73,0.75,0.77,0.79,0.77,0.75,0.73,0.71,0.69,0.67,0.65,0.63,0.61,0.59,0.57,0.55,0.53,0.51,0.49),
sd=c(0.09,0.087,0.082,0.08,0.023,0.011,0.010,0.009,0.008,0.007,0.006,0.005,0.004,0.003,0.002,0.001,0.002,0.003,0.004,0.005,0.006,0.007,0.008,0.009,0.010,0.011,0.023,0.08,0.084,0.087,0.09))
Plot <- ggplot(df, aes(x=time, y=mean)) +
geom_errorbar(aes(ymin=mean-sd, ymax=mean+sd), width=.3) +
geom_point(size=1) +
geom_line () +
theme_bw() +
scale_y_continuous(limits = c(0.49, 0.85), breaks = c(0.5, 0.65,0.8))
Plot
You need to set coord_cartesian limits rather than scale_y_continuous limits:
ggplot(df, aes(x=time, y=mean)) +
geom_errorbar(aes(ymin=mean-sd, ymax=mean+sd), width=.3) +
geom_point(size=1) +
geom_line () +
theme_bw() +
scale_y_continuous(breaks = c(0.5, 0.65,0.8)) +
coord_cartesian(ylim = c(0.49, 0.85))
How to get rid of all this space where the blue lines are?
Data:
data = data.frame(is_repeat = c(0,0,0,1,1,1,1,1,1,1),
value = c(12000,8000,20000,14000,15000,11000,20000,60000,20000, 20000))
data$is_repeat = factor(data$is_repeat, levels = c(0,1),
labels = c("One-time", "Repeat"))
Plot:
ggplot(data, aes(is_repeat, value)) +
geom_bar(stat = "identity", width = 0.3) +
ggtitle("Title") +
xlab("Type of event") +
ylab("Total Value") +
ylim(0, 150000) +
theme_minimal()
edit: I looked at that question and it did NOT solve my problem. My guess is that in the other question's plot, there are 4 bars, so it looks filled. I want to reduce the total width of the X axis.
another edit: Added data.
If you are looking to remove the space between the bars completely and you don't mind the width of bars you could do it with:
geom_bar(stat="identity", position="stack", width=1)
or theme(aspect.ratio=1)
And to remove the space from the end of the plot to the bars you need
scale_x_discrete(expand = c(0,0), limits=c("One-time", "Repeat"))
So your code looks like this:
ggplot(data, aes(is_repeat, value)) +
geom_bar(stat="identity", position="stack", width=1) +
ggtitle("Title") +
xlab("Type of event") +
ylab("Total Value") +
ylim(0, 150000) +
scale_x_discrete(expand = c(0,0), limits=c("One-time", "Repeat")) +
theme_minimal()
And the output:
You can add space between bars with changing the width=1
Using the this code gives the plot printed below. As you can see the percentages are printed on the border of the bars. I would like to have them above the bars. Is there a way to achieve this?
p <- ggplot(data=iris, aes(x=factor(Species), fill=factor(Species)))
p + geom_bar() + scale_fill_discrete(name="Species") + labs(x="") +geom_text(aes(y = (..count..),label = scales::percent((..count..)/sum(..count..))), stat="bin",colour="darkgreen") + theme(legend.position="none")
Just add an arbitrary value to y.
p <- ggplot(data=iris, aes(x=factor(Species), fill=factor(Species)))
p + geom_bar() + scale_fill_discrete(name="Species") + labs(x="") +geom_text(aes(y = (..count..) + 10,label = scales::percent((..count..)/sum(..count..))), stat="bin",colour="darkgreen") + theme(legend.position="none")
Or, as per Heroka's comment, use vjust, which is a better solution
p <- ggplot(data=iris, aes(x=factor(Species), fill=factor(Species)))
p + geom_bar() + scale_fill_discrete(name="Species") + labs(x="") +
geom_text(aes(y = (..count..),
label = scales::percent((..count..)/sum(..count..))),
stat="bin",
colour="darkgreen", vjust = -0.5) +
theme(legend.position="none")
But as this makes things quite cramped at the top you might want to add + expand_limits(y = c(0, 60)) to give you a bit more space for the labels.
I want to produce a plot with ggplot2 and geom_tile(). I want the tiles to have same height and width, which seems to work fine if both x and y axis are discrete (as was discussed here: adjust ggplot2 geom tile height and width).
If I have values on the x axis that are interpreted as continuous, however, I either get a lot of grey space in the plot and no aspect ratio of 1 when I use a discrete scale for the x axis (MWE1), or I do get a plot without grey space with a continuous scale but still no aspect ratio of 1 (MWE2). (I would insert images but it seems it is not allowed because my reputation is not high enough.)
MWE1:
my <- data.frame(x=c(rep(c(0.1),3),rep(c(0.3),3),rep(c(0.5),3)),y=rep(c("frac(SP1)=0.5", "frac(SP1)=0.7", "frac(SP2)=0,3"),3),z=sample(seq(1:50),9))
p <- ggplot(my, aes(x, y)) + geom_tile(aes(fill = z)) +
scale_fill_gradient(low = "white",high = "steelblue") +
theme_grey() +
labs(x = "", y= "") +
scale_x_discrete(expand = c(0,0)) +
scale_y_discrete(expand = c(0,0)) +
coord_fixed(ratio=1) +
theme(axis.ticks = element_blank())
MWE2:
my <- data.frame(x=c(rep(c(0.1),3),rep(c(0.3),3),rep(c(0.5),3)),y=rep(c("frac(SP1)=0.5", "frac(SP1)=0.7", "frac(SP2)=0,3"),3),z=sample(seq(1:50),9))
p <- ggplot(my, aes(x, y)) + geom_tile(aes(fill = z)) +
scale_fill_gradient(low = "white",high = "steelblue") +
theme_grey() +
labs(x = "", y= "") +
scale_x_continuous(breaks=c(0.1,0.3,0.5),expand = c(0,0)) +
scale_y_discrete(expand = c(0,0)) +
coord_fixed(ratio=1) +
theme(axis.ticks = element_blank())
Is there a way that I can still control aspect ratio when dealing with discrete and continuous scale? Or a way to tell ggplot2 to interpret the x values as discrete?
I'm not sure I quite understand your question, but I think this is what you want:
p <- ggplot(my, aes(factor(x), y)) + geom_tile(aes(fill = z)) +
scale_fill_gradient(low = "white",high = "steelblue") +
theme_grey() +
labs(x = "", y= "") +
coord_fixed() +
theme(axis.ticks = element_blank())
print(p)
I converted your x variable to a factor since it's not really continuous anyways. Now you get a 3x3 heatmap: