Multiple lines on multiple plots in R - r

I am looking for a workaround to plot smoothed time series for different time series on the same plot. I know I could use par(mfrow(c(4,1)) to get multiple plots on the same graph. But i want to have the same X-axis for the graph. so that I have something like below.
I have plotted after combining the data sets using cbind.
Now i want to have the smoothed plots corresponding to each time series in the same graph. By using par i get the following result.
But i do not want the label for the x-axis everywhere. I have used lines in every plot to get the above result.
par(mfrow=c(4,1))
plot.ts(ts1,col="green")
lines(SMA(ts1,n=10),col="red")
plot.ts(ts2,col="green")
lines(SMA(ts2,n=10),col="red")
plot.ts(ts3,col="green")
lines(SMA(ts3,n=10),col="red")
plot.ts(ts4,col="green")
lines(SMA(ts4,n=10),col="red")
is there any way I could get the desired result using plot or ggplot in R?

With ggplot try this:
ts1 <- rnorm(100) # randomly generated values for times series
ts2 <- rnorm(100)
ts3 <- rnorm(100)
ts4 <- rnorm(100)
library(TTR)
df <- data.frame(time=rep(1:100, 8),
id=as.factor(rep(1:8, each=100)), id1=as.factor(rep(1:4, each=200)),
type=as.factor(rep(rep(1:2, each=100),4)),
value=c(ts1, SMA(ts1), ts2, SMA(ts2), ts3, SMA(ts3), ts4, SMA(ts4)))
library(ggplot2)
ggplot(df, aes(time, value, col=type, group=id)) +
geom_line() + facet_wrap(~id1, ncol=1) +
scale_color_manual(values=c('green', 'red'))+
guides(color=FALSE) + theme_bw() + theme(strip.text = element_blank())
If you want different y labels for facets, try this:
library(grid)
library(gridExtra)
grid.arrange(ggplot(data.frame(time=rep(1:100, 2), id=as.factor(rep(1:2, each=100)),
type=as.factor(rep(1:2, each=100)),
ts1=c(ts1, SMA(ts1))), aes(time, ts1, col=type, group=id)) +
geom_line() + scale_color_manual(values=c('green', 'red')) + guides(color=FALSE) +
theme_bw() + theme(axis.text.x = element_blank(), axis.ticks = element_blank()) + xlab(''),
ggplot(data.frame(time=rep(1:100, 2), id=as.factor(rep(1:2, each=100)),
type=as.factor(rep(1:2, each=100)),
ts2=c(ts2, SMA(ts2))), aes(time, ts2, col=type, group=id)) +
geom_line() + scale_color_manual(values=c('green', 'red')) + guides(color=FALSE) +
theme_bw() + theme(axis.text.x = element_blank(), axis.ticks = element_blank()) + xlab(''),
ggplot(data.frame(time=rep(1:100, 2), id=as.factor(rep(1:2, each=100)),
type=as.factor(rep(1:2, each=100)),
ts3=c(ts3, SMA(ts3))), aes(time, ts3, col=type, group=id)) +
geom_line() + scale_color_manual(values=c('green', 'red')) + guides(color=FALSE) +
theme_bw() + theme(axis.text.x = element_blank(), axis.ticks = element_blank()) + xlab(''),
ggplot(data.frame(time=rep(1:100, 2), id=as.factor(rep(1:2, each=100)),
type=as.factor(rep(1:2, each=100)),
ts4=c(ts4, SMA(ts4))), aes(time, ts4, col=type, group=id)) +
geom_line() + scale_color_manual(values=c('green', 'red')) + guides(color=FALSE) + theme_bw(), ncol=1)

Related

Displaying a subset of features in a facet of a multi-layer plot

I'm trying to generate a multi-layered plot where the points in one layer gets displayed only in a fraction of the facets created using data from another layer. In the code below, the points in red are either x1 or x2 (just like the row labels of the facet).
library(ggplot2)
set.seed(1000)
#generate first df
df1 = data.frame(x=rep(rep(seq(2,8,2),4),4),
y=rep(rep(seq(2,8,2),each=4),4),
v1=rep(c("x1","x2"),each=32),
v2=rep(rep(c("t1","t2"),each=16),2),
v3=rbinom(64,1,0.5))
# generate second df
df2 = data.frame(x=runif(20)*10,
y=runif(20)*10,
v4=sample(c("x1","x2"),20,T))
# create theme
t1=theme(panel.grid.major = element_blank(), text = element_text(size=18),
panel.grid.minor = element_blank(), strip.background= element_blank(),
axis.title.x = element_blank(), axis.title.y = element_blank())
# plot
ggplot() +
geom_point(data=df1, aes(x=x, y=y, colour = factor(v3)), shape=15, size=5) +
scale_colour_manual(values = c(NA,"black")) + facet_grid(v1~v2) +
geom_point(data=df2, aes(x=x,y=y, shape=v4), colour="red", size=4) +
coord_equal(ratio=1) + xlim(0, 10) + ylim(0, 10) + t1
EDIT: The black squares are generated by manually setting the colour of df1$v3 = 1 to black and df1$v3 = 0 to NA. /EDIT
But what I actually want is to display only those points from df2 with df2$v4 = x1 in the first row of facets, and df2$v4 = x2 in the second row of facets (corresponding to the values of df1$v1 and the row labels of the facet).
I've done this by generating two separate graphs...
ggplot() +
geom_point(data=df1[df1$v1=="x1",], shape=15, size=5,
aes(x=x, y=y, colour = factor(v3)), ) +
scale_colour_manual(values = c(NA,"black")) + facet_grid(~v2) +
geom_point(data=df2[df2$v4=="x1",], aes(x=x,y=y), colour="red", size=4) +
coord_equal(ratio=1) + xlim(0, 10) + ylim(0, 10) + t1
ggplot() +
geom_point(data=df1[df1$v1=="x2",], shape=15, size=5,
aes(x=x, y=y, colour = factor(v3)), ) +
scale_colour_manual(values = c(NA,"black")) + facet_grid(~v2) +
geom_point(data=df2[df2$v4=="x2",], aes(x=x,y=y), colour="red", size=4) +
coord_equal(ratio=1) + xlim(0, 10) + ylim(0, 10) + t1
... but I'm curious if a single plot can be generated because with my actual data set I have several x's and it is time consuming to piece the graphs together.
does it help if we just rename df2$v4 or make a new column called df2$v1, for faceting purposes:
df2 <- dplyr::rename(df2, v1 = v4)
df2$v1 <- df2$v4
# either works
then ggplot will distribute the data points as you would like, with this:
ggplot() +
geom_point(data=df1, aes(x=x, y=y, colour = factor(v3)), shape=15, size=5) +
scale_colour_manual(values = c(NA,"black")) +
facet_grid(v1~v2) +
geom_point(data=df2, aes(x=x,y=y), colour="red", size=4) +
coord_equal(ratio=1) + xlim(0, 10) + ylim(0, 10) +
t1
not 100% sure I grasp your problem...

ggplot: (manually) create legend when referencing different data.frames

Ok, lets take some sample data.
A <- sample(1:100, 25)
B <- sample(1:25, 25)
df.1 <- data.frame(A,B)
C <- sample(1:80, 15)
D <- sample(1:15, 15)
df.2 <- data.frame(C,D)
Then we plot the data using ggplot
library(ggplot2)
(plot2 <- ggplot(NULL) +
geom_point(data=df.1, aes(x=A, y=B),
color='black', cex=1, pch=16 ) +
geom_smooth(data=df.1, aes(x=A, y=B), method="lm", size=1,
se=FALSE, colour="black", linetype=2)+
geom_point(data=df.2, aes(x=C, y=D),
color='black', cex=1, pch=15 ) +
geom_smooth(data=df.2, aes(x=C, y=D), method="lm", size=1,
se=FALSE, colour="black", linetype=1)+
scale_y_continuous("Y scale") +
ggtitle("Plot") +
theme_bw()+
theme(plot.title = element_text(face="bold", size=20),
axis.title.x = element_text(vjust=-0.25),
axis.title.y = element_text(vjust=1),
axis.title = element_text(face="bold", size=15)
)
)
So we have created and modified the title, axis, etc.
But I want to create a legend which shows the linetype's from the geom_smooth() function of df.1 and df.2. It should be in the top right of the graph.
(so for df.1 we want a solid line and df.2 a dashed line)
The example here walks you through an example, but the data comes from within the same data set
Here you go:
#combine and create x and y (as mappings follow
#same pattern)
df.1$group <- "df.1"
df.1$x <- df.1$A
df.1$y <- df.1$B
df.2$group <- "df.2"
df.2$x <- df.2$C
df.2$y <- df.2$D
library(plyr) #for rbind.fill
df.all <- rbind.fill(df.1,df.2)
plot3 <- ggplot(df.all, aes(x=x,y=y,group=group)) +
geom_point(color='black', cex=1, pch=16 ) +
geom_smooth(aes(linetype=group),method="lm", size=1,
se=FALSE, colour="black") +
scale_y_continuous("Y scale") +
ggtitle("Plot") +
theme_bw()+
theme(plot.title = element_text(face="bold", size=20),
axis.title.x = element_text(vjust=-0.25),
axis.title.y = element_text(vjust=1),
axis.title = element_text(face="bold", size=15)
) +
#add custom linetypes (not necessary now, as default mapping to 1 and 2)
plot3 + scale_linetype_manual(values=c("df.1"=1,"df.2"=2))

R ggplot : Can't change y-axis scale range with facetted plot

I have a simple problem but I can't figure out why it won't work -> I can't adjust the y scale range on my faceted bar plot:
# Data #
df<-as.data.frame(c("x","y","z","x","y","z","x","y","z","x","y","z"))
colnames(df)<-"x"
df$y<-c(10,15,20,5,25,45,10,10,20,40,20,5)
df$facet<-c(1,1,1,1,1,1,2,2,2,2,2,2)
df$group<-c("A","A","A","B","B","B","A","A","A","B","B","B")
# Plot #
ggplot(df, aes(x=x, y=y, fill=group)) +
facet_grid( ~ facet) +
scale_fill_manual(values=c("blue", "red")) +
geom_bar(position="dodge", stat="identity") +
theme(strip.text = element_text(face="bold", size=rel(1)),
strip.background = element_rect(fill="white", colour="white", size=1)) +
theme(panel.margin = unit(1, "lines")) +
scale_x_discrete(expand = c(0, 0)) +
theme(panel.grid.major.x = element_blank()) + theme(axis.ticks.x = element_blank()) +
theme(legend.background=element_blank()) +
scale_y_continuous("%", breaks=seq(0, 50, 10), minor_breaks=seq(0,50,5), expand = c(0, 0))
I would like the y-axis to go upto 50 but using scale_y_continuous strangely does not work, producing this result:
You need to add a limits argument in your scale_y_continuous :
scale_y_continuous("%", limits=c(0,50), breaks=seq(0, 50, 10), minor_breaks=seq(0,50,5), expand = c(0, 0))
Otherwise you just define the breaks position, not the axis values range.

Changing x-axis to discrete alters margins

I have a plot produced with the following code:
plot <- ggplot(lmeans, aes(x=Day, y=value*100, group=variable, colour=variable)) +
geom_point(aes(shape=variable), size=4) +
geom_line(aes(linetype=variable), size=1.5) +
ggtitle(paste("Nausea and Vomitting Frequencies by Day for", group_name)) +
ylab("Frequency (%)") +
ylim(0, 40) +
theme(legend.title=element_blank()) +
theme(legend.justification = c(1, 1), legend.position = c(1, 1))
Which results in a plot like so:
However I would like the days to be discretely labeled rather than being given as a continuous axis. When I try to achieve this by adding scale_x_discrete(), I get the following result:
In which the 'margins' on the x-axis are altered in an unsightful manner. How can I avoid these unsightly changes?
Here's a minimal example for reproduction:
require(ggplot2)
lmeans <- data.frame(Day=c(0,1,2,3,0,1,2,3),
variable=c("x","x","x","x","y","y","y","y"),
value=c(5,4,2,1,7,3,2,0))
plot <- ggplot(lmeans, aes(x=Day, y=value, group=variable, colour=variable)) +
geom_point(aes(shape=variable)) +
geom_line(aes(linetype=variable)) +
ylim(0, 10) +
scale_x_discrete() +
theme(legend.justification = c(1, 1), legend.position = c(1, 1))
print(plot)
Which produces this:
Without scale_x_discrete and setting Day as a factor, the plot is looking OK:
ggplot(lmeans, aes(x=factor(Day), y=value, group=variable, colour=variable)) +
geom_point(aes(shape=variable), size=4) +
geom_line(aes(linetype=variable), size=1.5) +
theme(legend.justification = c(1, 1), legend.position = c(1, 1))
which gives:
When you use scale_x_discrete, you can include the expand parameter in order to set the margins. An example:
ggplot(lmeans, aes(x=factor(Day), y=value, group=variable, colour=variable)) +
geom_point(aes(shape=variable), size=4) +
geom_line(aes(linetype=variable), size=1.5) +
ylim(0, 10) +
scale_x_discrete("Day", expand=c(0.05,0.1), breaks=c(0,1,2,3)) +
theme(legend.justification = c(1, 1), legend.position = c(1, 1))
which gives:
I changed scale_x_discrete() to scale_x_continuous() and used limits. Does this work for you?
ggplot(lmeans, aes(x=Day, y=value, group=variable, colour=variable)) +
geom_point(aes(shape=variable)) +
geom_line(aes(linetype=variable)) +
ylim(0, 10) +
scale_x_continuous(limits = c(-0.5, 4)) +
theme(legend.justification = c(1, 1), legend.position = c(1, 1))
Use factor(Day) in the aesthetic mapping:
plot <- ggplot(lmeans, aes(x=factor(Day), y=value,
group=variable, colour=variable)) +
geom_point(aes(shape=variable)) +
geom_line(aes(linetype=variable)) +
ylim(0, 10) +
labs(x="Day") +
theme(legend.justification=c(1, 1), legend.position=c(1, 1))
print(plot)

Overlay density of one variable on trend line

I have some data:
dat <- data.frame(x=rnorm(100,100,100),y=rnorm(100,100,100))
I can plot it with a local trend line:
ggplot(dat, aes(x,y)) + stat_smooth()
But I want to overlay a density curve, on the same plot, showing the distribution of x. So just add the previous graph to this one (the y-axis is different, but I only care about relative differences in the density curve anyway):
ggplot(dat, aes(x)) + geom_density()
I know there's stat_binhex() and stat_sum() etc showing where the data falls. There are only a few y values, so what gets plotted by stat_binhex() etc is hard to read.
You can plot a combination of histograms and density curves at both sides of the scatterplot. In the example below I also included a confidence ellipse:
require(ggplot2)
require(gridExtra)
require(devtools)
source_url("https://raw.github.com/low-decarie/FAAV/master/r/stat-ellipse.R") # in order to create a 95% confidence ellipse
htop <- ggplot(data=dat, aes(x=x)) +
geom_histogram(aes(y=..density..), fill = "white", color = "black", binwidth = 2) +
stat_density(colour = "blue", geom="line", size = 1.5, position="identity", show_guide=FALSE) +
scale_x_continuous("x-var", limits = c(-200,400), breaks = c(-200,0,200,400)) +
scale_y_continuous("Density", breaks=c(0.0,0.01,0.02), labels=c(0.0,0.01,0.02)) +
theme_bw() + theme(axis.title.x = element_blank())
blank <- ggplot() + geom_point(aes(1,1), colour="white") +
theme(axis.ticks=element_blank(), panel.background=element_blank(), panel.grid=element_blank(),
axis.text.x=element_blank(), axis.text.y=element_blank(), axis.title.x=element_blank(), axis.title.y=element_blank())
scatter <- ggplot(data=dat, aes(x=x, y=y)) +
geom_point(size = 0.6) + stat_ellipse(level = 0.95, size = 1, color="green") +
scale_x_continuous("x-var", limits = c(-200,400), breaks = c(-200,0,200,400)) +
scale_y_continuous("y-var", limits = c(-200,400), breaks = c(-200,0,200,400)) +
theme_bw()
hright <- ggplot(data=dat, aes(x=y)) +
geom_histogram(aes(y=..density..), fill = "white", color = "black", binwidth = 1) +
stat_density(colour = "red", geom="line", size = 1, position="identity", show_guide=FALSE) +
scale_x_continuous("y-var", limits = c(-200,400), breaks = c(-200,0,200,400)) +
scale_y_continuous("Density", breaks=c(0.0,0.01,0.02), labels=c(0.0,0.01,0.02)) +
coord_flip() + theme_bw() + theme(axis.title.y = element_blank())
grid.arrange(htop, blank, scatter, hright, ncol=2, nrow=2, widths=c(4, 1), heights=c(1, 4))
the result:

Resources