ggplot2: smooth and fill - r

I'd like to smooth the geom_lines and fill the area between. I've tried stat_smooth() to smooth the lines, and both geom_ribbon() and geom_polygon() but without success.
Apologies for the double barrel question.
bell <- data.frame(
month = c("Launch","1st","2nd","3rd","4th","5th","6th","7th","8th","9th","10th","11th","12th"),
rate = c(0,.05,.12,.18,.34,.42,.57,.68,.75,.81,.83,.85,.87))
bell$month <- factor(bell$month, levels = rev(c("Launch","1st","2nd","3rd","4th","5th","6th","7th","8th","9th","10th","11th","12th")))
ggplot() +
theme_minimal() +
coord_flip() +
scale_fill_manual(values=cols) +
geom_line(data=bell, aes(x=month, y=.5-(rate/2), group=1), color='pink', size=1) +
geom_line(data=bell, aes(x=month, y=.5+(rate/2), group=1), color='pink', size=1) +
theme(legend.position='none', axis.ticks=element_blank(), axis.text.x=element_blank(),axis.title.x=element_blank())

One option is to calculate the points of the loess regression outside of ggplot and then plot them using geom_line (for a line) or geom_area for a filled area (geom_area is geom_ribbon, but with ymin fixed at zero).
Also, you don't need coord_flip. Instead, just switch your x and y mappings. This is necessary anyway if you want to fill underneath the curve.
In the example below I've created a numeric month variable for the regression. I've also commented out the scale_fill_manual line because your example doesn't provide a cols vector and the plot code doesn't produce a legend anyway. I've also commented out the legend.position='none' line as it's superfluous.
bell$month.num = 0:12
m1 = loess(rate ~ month.num, data=bell)
bell$loess.mod = predict(m1)
ggplot(bell, aes(y=month, group=1)) +
theme_minimal() +
#scale_fill_manual(values=cols) +
geom_area(aes(x=.5-(loess.mod/2)), fill='pink', size=1) +
geom_area(aes(x=.5+(loess.mod/2)), fill='pink', size=1) +
theme(#legend.position='none',
axis.ticks=element_blank(),
axis.text.x=element_blank(),
axis.title.x=element_blank())

Related

Duplicated xtick labels in ggplot facets

I have this data.frame which I want to plot in facets using ggplot + facet_wrap:
set.seed(1)
df <- data.frame(val=rnorm(36),
gt=c(sapply(c("wt","pd","md","bd"),function(x) rep(x,9))),
ts=rep(c(sapply(c("cb","hp","ac"),function(x) rep(x,3))),4),
col=c(sapply(c("darkgray","darkblue","darkred","darkmagenta"),function(x) rep(x,9))),
index=rep(1:9,4),
stringsAsFactors=F)
df$xlab <- paste(df$ts,df$index,sep=".")
df$gt <- factor(df$gt,levels=c("wt","pd","md","bd"))
Here's how I'm trying to plot:
require(ggplot2)
ggplot(df,aes(x=index,y=val,color=gt))+geom_point(size=3)+facet_wrap(~gt,ncol=4)+
scale_fill_manual(values=c("darkgray","darkblue","darkred","darkmagenta"),labels=levels(df$gt),name="gt",guide=F)+
scale_colour_manual(values=c("darkgray","darkblue","darkred","darkmagenta"),labels=levels(df$gt),name="gt",guide=F)+
labs(x="replicate",y="val")+scale_x_continuous(breaks=df$index,labels=df$xlab)+
theme_bw()+theme(axis.text=element_text(size=6),axis.title=element_text(size=7),legend.text=element_text(size=6),legend.key=element_blank(),panel.border=element_blank(),strip.background=element_blank())
Which gives:
The problem is that the x0axis tick labels repeat themselves, sinceI'm calling scale_x_continuous. How do I get it right with facet_wrap?
Use the actual x-values in xlab as the x aesthetic, along with scales="free_x" in facet_wrap and delete the call to scale_x_continuous. Note, however, that the axis labels are still the same in each panel, because they are the same for each level of gt in the data.
ggplot(df,aes(x=xlab, y=val, color=gt)) +
geom_point(size=3, show.legend=FALSE) +
facet_wrap(~gt, ncol=4, scales="free_x") +
# scale_fill_manual(values=c("darkgray","darkblue","darkred","darkmagenta"), labels=levels(df$gt), name="gt", guide=F) +
scale_colour_manual(values=c("darkgray","darkblue","darkred","darkmagenta")) +
labs(x="replicate", y="val") +
#scale_x_continuous(breaks=df$index, labels=df$xlab)+
theme_bw() +
theme(axis.text=element_text(size=8),
axis.title=element_text(size=7),
legend.text=element_text(size=6),
legend.key=element_blank(),
panel.border=element_blank(),
strip.background=element_blank())
Now let's change xlab, just to see how this works when different panels really do have different labels:
df$xlab[10:20] = LETTERS[1:11]
Now run the same plot code again to get the following:
One more contingency is the case where not all the panels have the same number of x-values. In that case, you can switch to facet_grid and add space="free_x" if you want the width of each panel to be proportional to the number of x-values in each panel.
ggplot(df[-c(1:5),], aes(x=xlab, y=val, color=gt)) +
geom_point(size=3, show.legend=FALSE) +
facet_grid(.~gt, space="free_x", scales="free_x") +
scale_colour_manual(values=c("darkgray","darkblue","darkred","darkmagenta")) +
labs(x="replicate", y="val") +
theme_bw() +
theme(axis.text=element_text(size=8),
axis.title=element_text(size=7),
legend.text=element_text(size=6),
legend.key=element_blank(),
panel.border=element_blank(),
strip.background=element_blank())
A few other things:
You don't need to add color names to your data frame. If you want to change the default color, you can just set the them using one of the scale_colour_*** functions (as you did in your code).
For future reference this c(sapply(c("darkgray","darkblue","darkred","darkmagenta"),function(x) rep(x,9))) can be changed to this rep(c("darkgray","darkblue","darkred","darkmagenta"), each=9).
You can remove the scale_fill_manual line, as you don't have a fill aesthetic in your graph.

ggplot. Adding regression lines by group

If I plot this
dodge <- position_dodge(.35)
ggplot(mediat, aes(x=t, y=Value, colour=factor(act),group=id )) +
geom_point(position=dodge) + geom_errorbar(aes(ymin=Value-sdt, ymax=Value+sdt),
width=0, position=dodge) + theme_bw() + geom_smooth(method="lm",se=FALSE,
fullrange=TRUE)
I get this
As you can see the regression line is not plotted.
with +stat_smooth(method=lm, fullrange=TRUE, se = FALSE) the result is the same.
I've found that removing the "group=id" I can get the regression lines but
then
ggplot(mediat, aes(x=t, y=Value, colour=factor(act) ))+ geom_point(position=dodge) +
geom_errorbar(aes(ymin=Value-sdt, ymax=Value+sdt), width=0, position=dodge) +
theme_bw() + geom_smooth(method="lm",se=FALSE, fullrange=TRUE)
As you can see, now it plot the lines but I loose the dodge function by groups.
How can I get both things at once?. I mean, regression lines by "id" on the first uncluttered plot?
Any other solution with base plot, lattice or any other common package would also be welcome.
Regards

Apply coord_flip() to single layer

I would like to have a boxplot showing the same distribution underneath my histogram.
The code below almost works, but coord_flip() is being applied to all layers, instead of just the geom_boxplot layer.
plot1<-ggplot(newdatahistogram, aes_string(x=newdatahistogram[RawLocation])) +
xlab(GGVar) + ylab("Proportion of Instances") +
geom_histogram(aes(y=..density..), binwidth=1, colour="black", fill="white",origin=-0.5) +
scale_x_continuous(limits=c(-3,6), breaks=seq(0,5,by=1), expand=c(.01,0)) +
geom_boxplot(aes_string(x=-1, y=newdatahistogram[RawLocation])) + coord_flip()
How can I apply coord_flip() to a single layer?
Thank you!
I got it to work with a bit of a hack;
plot1 <- ggplot(newdatahistogram, aes_string(x=newdatahistogram[RawLocation], fill=(newdatahistogram[,"PQ"]))) +
xlab(GGVar) + ylab("Proportion of Observation") +
geom_histogram(aes(y=..density..), binwidth=1, colour="black", origin=-0.5) +
scale_x_continuous(limits=c(-1,6), breaks=seq(0,5,by=1), expand=c(.01,0)) +
scale_y_continuous(limits=c(-.2,1), breaks=seq(0,1,by=.2))
theme(plot.margin = unit(c(0,0,0,0), "cm"))
plot_box <- ggplot(newdatahistogram) +
geom_boxplot(aes_string(x=1, y=newdatahistogram[RawLocation])) +
scale_y_continuous(breaks=(0:5), labels=NULL, limits=c(-1,6), expand=c(.0,-.03)) +
scale_x_continuous(breaks=NULL) + xlab(NULL) + ylab(NULL) +
coord_flip() + theme_bw() +
theme(plot.margin = unit(c(0,0,.0,0), "cm"),
line=element_blank(),text=element_blank(),
axis.line = element_blank(),title=element_blank(), panel.border=theme_blank())
PB = ggplotGrob(plot_box)
plot1 <- plot1 + annotation_custom(grob=PB, xmin=-1.01, xmax=5.95, ymin=-.3,ymax=0)
This saves the rotated boxplot as a grob object and inserts it into the plot under the histogram.
I needed to play with the expansion element a bit to get the scales to line up,
but it works!
Seriously though, I think ggplot should have a horizontal boxplot available without cord_flip()... I tried to edit the boxplot code, but it was way too difficult for me!
Tried to post image, but not enough reputation
You can't: coord_flip always acts on all layers. However, you do have two alternatives:
The solution here shows how to use grid.arrange() to add a marginal histogram. (The comments in the question also link to a nice base-R way to do the same thing)
You could indicate density using a rug plot on of the four sides of the plot with plot1 + geom_rug(sides='r')
ggplot(mpg, aes(x=class, y=cty)) +
geom_boxplot() + geom_rug(sides="r")

Plot two regression lines (calculated on subset of the same data frame) on the same graph with ggplot

I have this kind of data frame:
df<-data.frame(x=c(1,2,3,4,5,6,7,8,9,10),y=c(2,11,24,30,45,65,90,110,126,145), a=c(0.2,0.2,0.3,0.4,0.1,0.8,0.7,0.6,0.8,0.9))
Using ggplot, I would like to plot on the same figure two regression lines, calculated for a subset of my data frame under condition (a > or < 0.5).
Visually, I would like that both regression lines:
df_a<-subset(df, df$a<0.5)
ggplot(df_a,aes(x,y))+
geom_point(aes(color = a), size=3.5) +
geom_smooth(method="lm", size=1, color="black") +
ylim(-5,155) +
xlim(0,11)
df_b<-subset(df, df$a>0.5)
ggplot(df_b,aes(x,y)) +
geom_point(aes(color = a), size=3.5) +
geom_smooth(method="lm", size=1, color="black") +
ylim(-5,155) +
xlim(0,11)
Appear on this figure:
ggplot(df,aes(x,y))+ geom_point(aes(color = a), size=3.5)
I've tried with par(new=TRUE) without success.
Make a flag variable, and use group:
df$small=df$a<0.5
ggplot(df,aes(x,y,group=small))+geom_point() + stat_smooth(method="lm")
and have yourself pretty colours and a legend if you want:
ggplot(df,aes(x,y,group=small,colour=small))+geom_point() + stat_smooth(method="lm")
Or maybe you want to colour the dots:
ggplot(df,aes(x,y,group=small)) +
stat_smooth(method="lm")+geom_point(aes(colour=a))

ggplot2: How to specify multiple fill colors for points that are connected by lines of different colors

I am new to ggplot2. I would like to create a line plot that has points on them where the points are filled with different colors than the lines (see the plot below).
Suppose the dataset I am working with is the one below:
set.seed(100)
data<-data.frame(dv=c(rnorm(30), rnorm(30, mean=1), rnorm(30, mean=2)),
iv=rep(1:30, 3),
group=rep(letters[1:3], each=30))
I tried the following code:
p<-ggplot(data, aes(x=iv, y=dv, group=group, pch=group)) + geom_line() + geom_point()
p + scale_color_manual(values=rep("black",3))+ scale_shape(c(19,20,21)) +
scale_fill_manual(values=c("blue", "red","gray"))
p + scale_shape(c(19,20,21)) + scale_fill_manual(values=c("blue", "red","gray"))
But I do not get what I want.I hope someone can point me to the right direction. Thanks!
scale_fill_manual(), scale_shape_manual() and scale_colour_manual() can be used only if you have set fill=, shape= or colour= inside the aes().
To change colour just for the points you should add colour=group inside geom_point() call.
ggplot(data, aes(x=iv, y=dv, group=group,shape=group)) +
geom_line() + geom_point(aes(colour=group)) +
scale_shape_manual(values=c(19,20,21))+
scale_colour_manual(values=c("blue", "red","gray"))

Resources