Controlling bg and fg in ggplot2 - r

I have a set of data that I am trying to plot.
I would like the fill (bg) to be controlled by a logical variable.
The only way I can make it work is by layering two sets of points.
Is there a better way?
require(ggplot2)
dat<-data.frame(
x=rep(1:10, 2),
val=c(rnorm(10, 10), rnorm(10, 12)),
grp=rep(c("A", "B"), each=10),
tf=sample(c(TRUE, FALSE), 20, replace=TRUE)
)
ggplot(dat, aes(x, val, col=grp))+
geom_line()+
geom_point(aes(alpha=tf), size=4)+
geom_point(shape=21, size=4, aes(fg=grp))

You can use a manual shape to do this.
ggplot(dat, aes(x, val, col=grp)) +
geom_line() +
geom_point(aes(shape=tf), size=4) +
scale_shape_manual(values=c(19,21))

Related

Inner ticks in ggplot

I want to add inner ticks to my plot given by a vector.
say my vector is myvec <- c(1,3,4:9, 12, 15)
and my plot:
library(ggplot2)
df <- data.frame(x=seq(1:100), y=sort(rexp(100, 2), decreasing = T))
ggplot(df, aes(x=x, y=y)) + geom_point() +
scale_y_continuous(limits = c(0, 4))
I now want to add inside facing ticks at x= myvec, y=0 in blue color. How do I do it?
Tried to work with this solution, but could not use the vector.
Annotate ggplot with an extra tick and label
Try This:
df2<- cbind.data.frame("myvec" = myvec, z= rep(0, length(myvec)))
ggplot(df, aes(x=x, y=y)) + geom_point() +
scale_y_continuous(limits = c(0, 4)) +
geom_point(data=df2, aes(x=myvec, y=z), shape = "\U2714", color = "blue", size= 2)

How to color geom_bar by y-axis values?

I'm making a standard bar plot with ggplot2 geom_bar. I'm trying to fill the bars with the highest values with a different color than the bars with the lowest values.
For example,
ggplot(mtcars, aes(x=as.factor(cyl) )) + geom_bar()
How can you color bars above 20 in red (e.g., E), bars from 10 to 20 in blue (B and D), and bars below 10 in orange (A and C).
Thanks for any insights!
I'm using geom_col and my actual code looks like this
ggplot(data, aes(x=State, y=Value)) +
geom_col()
You might use cut
ggplot(mtcars, aes(x = as.factor(cyl))) +
geom_bar(aes(fill = cut(stat(count), breaks = c(0, 8, 12, Inf)))) +
labs(fill = "Breaks")
You obviously need to adjust the breaks according to your needs / data.
edit
If we use geom_col instead of geom_bar we need to change fill = stat(count) to fill = value_column (whatever the value_column is but it should be the same as the one we mapped to y).
Example:
df <- data.frame(trt = c("a", "b", "c"), outcome = c(2.3, 1.9, 3.2))
ggplot(df, aes(trt, outcome)) +
geom_col(aes(fill = cut(outcome, breaks = c(0, 2, 3, Inf)))) +
labs(fill = "Breaks")

How to jitter both geom_line and geom_point by the same magnitude?

I have a ggplot2 linegraph with two lines featuring significant overlap. I'm trying to use position_jitterdodge() so that they are more visible, but I can't get the lines and points to both jitter in the same way. I'm trying to jitter the points and line horizontally only (as I don't want to suggest any change on the y-axis). Here is an MWE:
## Create data frames
dimension <- factor(c("A", "B", "C", "D"))
df <- data.frame("dimension" = rep(dimension, 2),
"value" = c(20, 21, 34, 32,
20, 21, 36, 29),
"Time" = c(rep("First", 4), rep("Second", 4)))
## Plot it
ggplot(data = df, aes(x = dimension, y = value,
shape = Time, linetype = Time, group = Time)) +
geom_line(position = position_jitterdodge(dodge.width = 0.45)) +
geom_point(position = position_jitterdodge(dodge.width = 0.45)) +
xlab("Dimension") + ylab("Value")
Which produces the ugly:
I've obviously got something fundamentally wrong here: What should I do to make the geom_point jitter follow the geom_line jitter?
Another option for horizontal only would be to specify position_dodge and pass this to the position argument for each geom.
pd <- position_dodge(0.4)
ggplot(data = df, aes(x = dimension, y = value,
shape = Time, linetype = Time, group = Time)) +
geom_line(position = pd) +
geom_point(position = pd) +
xlab("Dimension") + ylab("Value")
One solution is to manually jitter the points:
df$value_j <- jitter(df$value)
ggplot(df, aes(dimension, value_j, shape=Time, linetype=Time, group=Time)) +
geom_line() +
geom_point() +
labs(x="Dimension", y="Value")
The horizontal solution for your discrete X axis isn't as clean (it's clean under the covers when ggplot2 does it since it handles the axis and point transformations for you quite nicely) but it's doable:
df$dim_j <- jitter(as.numeric(factor(df$dimension)))
ggplot(df, aes(dim_j, value, shape=Time, linetype=Time, group=Time)) +
geom_line() +
geom_point() +
scale_x_continuous(labels=dimension) +
labs(x="Dimension", y="Value")
On July 2017, developpers of ggplot2 have added a seed argument on position_jitter function (https://github.com/tidyverse/ggplot2/pull/1996).
So, now (here: ggplot2 3.2.1) you can pass the argument seed to position_jitter in order to have the same jitter effect in geom_point and geom_line (see the official documentation: https://ggplot2.tidyverse.org/reference/position_jitter.html)
Note that this seed argument does not exist (yet) in geom_jitter.
ggplot(data = df, aes(x = dimension, y = value,
shape = Time, linetype = Time, group = Time)) +
geom_line(position = position_jitter(width = 0.25, seed = 123)) +
geom_point(position = position_jitter(width = 0.25, seed = 123)) +
xlab("Dimension") + ylab("Value")

In ggplot2, how to add text by group in facet_wrap?

Here is an example:
library(ggplot2)
set.seed(112)
df<-data.frame(g=sample(c("A", "B"), 100, T),
x=rnorm(100),
y=rnorm(100,2,3),
f=sample(c("i","ii"), 100, T))
ggplot(df, aes(x=x,y=y, colour=factor(g)))+
geom_point()+geom_smooth(method="lm", fill="NA")+facet_wrap(~f)
My question is how to add text like the second plot by group into the plot.
You can manually create another data.frame for your text and add the layer on the original plot.
df_text <- data.frame(g=rep(c("A", "B")), x=-2, y=c(9, 8, 9, 8),
f=rep(c("i", "ii"), each=2),
text=c("R=0.2", "R=-0.3", "R=-0.05", "R=0.2"))
ggplot(df, aes(x=x,y=y, colour=factor(g))) +
geom_point() + geom_smooth(method="lm", fill="NA") +
geom_text(data=df_text, aes(x=x, y=y, color=factor(g), label=text),
fontface="bold", hjust=0, size=5, show.legend=FALSE) +
facet_wrap(~f)
Another option is to calculate the correlations on the fly and use the underlying numeric values of the factor variable g to place the text so that the red and blue labels don't overlap. This reduces the amount of code needed and makes label placement a bit easier.
library(dplyr)
ggplot(df, aes(x=x, y=y, colour=g)) +
geom_point() +
geom_smooth(method="lm", fill=NA) + # Guessing you meant fill=NA here
#geom_smooth(method="lm", se=FALSE) # Better way to remove confidence bands
facet_wrap(~f) +
geom_text(data=df %>% group_by(g, f) %>% summarise(corr = cor(x,y)),
aes(label=paste0("R = ", round(corr,2)), y = 10 - as.numeric(g)),
x=-2, hjust=0, fontface="bold", size=5, show.legend=FALSE)

Plot with multiple breaks of different sizes

I would like to create a plot with multiple breaks of different sized intervals on the y axis. The closest post I could find is this Show customised X-axis ticks in ggplot2 But it doesn't fully solve my problem.
# dummy data
require(ggplot2)
require(reshape2)
a<-rnorm(mean=15,sd=1.5, n=100)
b<-rnorm(mean=1500,sd=150, n=100)
df<-data.frame(a=a,b=b)
df$x <- factor(seq(100), ordered = T)
df.m <- melt(df)
ggplot(data = df.m, aes(x = x, y=value, colour=variable, group=variable)) +
geom_line() + scale_y_continuous(breaks = c(seq(from = 0, to = 20, by = 1),
seq(from = 1100, to = max(y), by = 100))) +
theme(axis.text.x = element_text(angle = 90, hjust = 1))
The problem is how to get the first set of breaks to be proportional to the second (thus visible).
Any pointer would be very much appreciated, thanks!
You can try something like this:
# Rearrange the factors in the data.frame
df.m$variable <- factor(df.m$variable, levels = c("b", "a"))
ggplot(data = df.m, aes(x = x, y=value, colour=variable, group=variable)) +
geom_line() + facet_grid(variable~., scales = "free")
Hope this helps

Resources