Facetting in ggplot2 - r

I have this dataset: https://dl.dropboxusercontent.com/u/73950/data.csv
The dataset contains 3 variables.
Here's how I visualize the data right now:
library(ggplot2)
library(reshape2)
library(RColorBrewer)
dat = read.csv("data.csv", header = FALSE)
myPalette <- colorRampPalette(rev(brewer.pal(11, "Spectral")))
sc <- scale_colour_gradientn(colours = myPalette(100))
ggplot(dat, aes(x=V1, y=V3, colour = V2))+ geom_point(alpha = .2,size = 3) + sc
Instead of just one figure, I'd like to facet the figure to display 3 different ways to attribute variables to each axis and color. As such:
x = V1, y = V2, color = V3
x = V1, y = V3, color = V2
x = V2, y = V3, color = V1
How to do this kind of things with ggplot2's faceting?

You can get this by putting the data in the format ggplot likes. In this case, a column that can be used to split the data into facets (called var below). To do that, I just repeated the data three times, choosing the appropriate x and y variables for each 2-way combo, and using the variable left out of each combination as the coloring variable.
## Rearrange the data by 2-way combinations, the coloring is the remaining column
res <- do.call(rbind, combn(1:3, 2, function(ii)
cbind(setNames(dat[,c(ii, setdiff(1:3, ii))], c("x", "y", "color")),
var=paste(ii, collapse=".")), simplify=F))
ggplot(res, aes(x=x, y=y, color=color))+ geom_point(alpha = .2,size = 3) +
facet_wrap(~ var, scales="free") + sc

Related

How to combine legends from different ggplot after extracting via get_legend

(EDIT: Removed original code and added reproducible example.)
I have two ggplot2 geom_tile plots.
Both have a legend.
The first one has one gradient scale.
The second one has two gradient scales.
Now I extract the legends from both plots via cowplot::get_legend(). The aim is to merge them to one legend and add it to the right of the composed final plot.
Then I try to combine them via: cowplot::plot_grid(legend1, legend2, ncol = 1, align = "v").
The problem is, that there is a large (EDIT: actually scaling) space between legend1 and legend2 (see figure below). I tried to remove margins of the legends via theme() when generating the initial geom_tile ggplots, but was not successful.
This there a way to completely "unwrap" the extracted legends and then stack them vertically afterwards into one ggplot figure?
Minimal example to showcase my problem:
m <- matrix(round(rnorm(200), 2), 10, 10)
colnames(m) <- paste("Col", 1:10)
rownames(m) <- paste("Row", 1:10)
df <- melt(m)
colnames(df) <- c("x", "y", "value")
df2 <- df
colnames(df2) <- c("x", "y", "value2")
library(ggnewscale)
ggplot1 <- ggplot(df, aes(x = x, y = y, fill = value)) +
geom_tile()
legend1 <- cowplot::get_legend(ggplot1)
ggplot2 <- ggplot() +
geom_tile(data = df2, aes(x = x, y = y, fill = value2)) +
ggnewscale::new_scale_fill() +
geom_tile(data = df, aes(x = x, y = y, fill = value))
legend2 <- cowplot::get_legend(ggplot2)
library(cowplot)
cowplot::plot_grid(legend1, legend2, ncol = 1, align = "v")
And here the result. The gap between the first scale and the second is too large -- what I learned just now, it that this large gap is being scaled according to the total size. So it seems to not be fixed:
When it comes to arranging plots it's always worthwhile to consider patchwork as an option. In your case you could use guides="collect" to arrange the legends without the need of extracting them first. However, at least for your example data one minor hack is necessary to show all legends, i.e. we have to add a space to the name of one of the value legends to prevent that they get merged.
library(ggplot2)
library(ggnewscale)
p1 <- ggplot(df, aes(x = x, y = y, fill = value)) +
geom_tile()
p2 <- ggplot() +
geom_tile(data = df2, aes(x = x, y = y, fill = value2)) +
ggnewscale::new_scale_fill() +
geom_tile(data = df, aes(x = x, y = y, fill = value)) +
scale_fill_continuous(name = "value ")
library(patchwork)
p1 / p2 + plot_layout(ncol = 1, guides = "collect")
DATA
set.seed(123)
m <- matrix(round(rnorm(100), 2), 10, 10)
colnames(m) <- paste("Col", 1:10)
rownames(m) <- paste("Row", 1:10)
df <- reshape2::melt(m)
colnames(df) <- c("x", "y", "value")
df2 <- df
colnames(df2) <- c("x", "y", "value2")

R: how to combine ggplots basd on data with different column names

Both ggplots below work separtely, but I would like to combine them to one plot where the Group variable of the lines in df2 appears in the legend.
library(ggplot2)
df1 <- data.frame(x = 1:10, y = 1:10)
df2 <- data.frame(x = rep(1:10,2),
y = c(seq(1,2,length.out = 10),
seq(5,6,length.out = 10)),
Group = c(rep("A",10),rep("B",10))
)
p1 <- ggplot(data = df1, aes(x = x, y = y)) +
geom_point()
p2<- ggplot(data = df2, aes(x = x, y = y,
group = Group, color = Group)) +
geom_line()
The problem is caused by the fact that 2 data frames have different column names. Therefore I cannot generate 2 plots and add them like p1 + p2 as it is done in other solutions that have been published here before.
First, in ggplot2 each layer has its own local data argument, i.e. you could pass a different dataset to each layer. If you don't set the data argument for a layer it will simply inherit the global dataset set in ggplot() (if any), i.e. you could combine your plots into one by adding + geom_line(data = df2, aes(group = Group, color = Group)) to your first plot.
Second, if your datasets have different column names that's not a big deal either. As with the data argument, each layer has it's own (local) set of aesthetics. If not set, a layer will inherit the global aesthetics set in ggplot(), i.e. with different column names you simply have to tell which columns should be mapped on the aesthetics in each layer.
Slightly altered your example data:
library(ggplot2)
df1 <- data.frame(x1 = 1:10, y1 = 1:10)
df2 <- data.frame(x2 = rep(1:10,2),
y2 = c(seq(1,2,length.out = 10),
seq(5,6,length.out = 10)),
Group = c(rep("A",10),rep("B",10))
)
ggplot(data = df1, aes(x = x1, y = y1)) +
geom_point() +
geom_line(data = df2, aes(x = x2, y = y2, group = Group, color = Group))

ggplot2: create a plot using selected facets with part data

I would like to create a plot with
Using part of the data to create a base plot with facet_grid of two columns.
Use remaining part of the data and plot on top of the existing facets but using only a single column.
The sample code:
library(ggplot2)
library(gridExtra)
df2 <- data.frame(Class=rep(c('A','B','C'),each=20),
Type=rep(rep(c('T1','T2'),each=10), 3),
X=rep(rep(1:10,each=2), 3),
Y=c(rep(seq(3,-3, length.out = 10),2),
rep(seq(1,-4, length.out = 10),2),
rep(seq(-2,-8, length.out = 10),2)))
g2 <- ggplot() + geom_line(data = df2 %>% filter(Class %in% c('B','C')),
aes(X,Y,color=Class, linetype=Type)) +
facet_grid(Type~Class)
g3 <- ggplot() + geom_line(data = df2 %>% filter(Class == 'A'),
aes(X,Y,color=Class, linetype=Type)) +
facet_wrap(~Type)
grid.arrange(g2, g3)
The output plots:
How to include g3 plot on g2 plot? The resulting plot should include the g3 two lines twice on two facets.
I assume the plot below is what you were looking for.
library(dplyr)
library(ggplot2)
df_1 <- filter(df2, Class %in% c('B','C')) %>%
dplyr::rename(Class_1 = Class)
df_2 <- filter(df2, Class == 'A')
g2 <- ggplot() +
geom_line(data = df_1,
aes(X, Y, color = Class_1, linetype = Type)) +
geom_line(data = df_2,
aes(X, Y, color = Class, linetype = Type)) +
facet_grid(Type ~ Class_1)
g2
explaination
For tasks like this I found it better to work with two datasets. Since the variable df2$class has three unique values: A, B and C, faceting Class~Type does not give you desired plot, since you want the data for df2$Class == "A" to be displayed in the respective facets.
That's why I renamed variable Class in df_1 to Class_1 because this variable only contains two unique values: B and C.
Faceting Class_1 ~ Type allows you to plot the data for df2$Class == "A" on top without being faceted by Class.
edit
Based on the comment below here is a solution using only one dataset
g2 + geom_line(data = filter(df2, Class == 'A')[, -1],
aes(X, Y, linetype = Type, col = "A"))
Similar / same question: ggplot2:: Facetting plot with the same reference plot in all panels

Plots with a common x axis

I have a data.frame df with columns T ,V1,V2,V3,V4
I would like to make a ggplot containing two plots with T as the common the x axis
The first plot contains V1
The second plot contains V2,V3,V4
I tried:
m1 <- melt(df, id = "T")
chart1<-qplot(T, value, data = m1, geom = "line", group = variable) +
stat_smooth() +
facet_grid(variable ~ ., scale = "free_y")
But this gives me four common plots whereas I just want two.
Is there a way to do this?
library(ggplot2)
library("reshape")
df <- data.frame(T,V1,V2,V3,V4)
m1 <- melt(df, id = "T")
m1$sepfac <- (m1$variable=="V1")
chart1<-qplot(T, value, data = m1, geom = "line", group = variable) +
stat_smooth() +
facet_grid(sepfac~., scale = "free_y")

Multiple colour-scaling with lower level plots of ggplot2

I would like to achieve a different colour gradient every time I add another a geom_line() to my main plot, each time with 'colour' as the scale.
Here is a data frame just as an example:
df <- data.frame("letter"=c(rep("a",5),rep("b",5)),"x"=rep(seq(1,5),2),"y1"=c(seq(6,10),seq(6,10)/2),"y2"=c(seq(1,5),seq(1,5)/2),"y3"=c(seq(3,7),seq(3,7)/2))
For which I first plot:
y1 <- ggplot(df,aes(x=x,y=y1,colour=letter))+geom_line()
y1
I then would like to add y1 and y2, which I can do as follows:
y2 <- geom_line(data=df,aes(x=x,y=y2,colour=letter))
y3 <- geom_line(data=df,aes(x=x,y=y3,colour=letter))
y1+y2+y3
But I would like the colour gradient (or hue) to be different for y1, y2 and y3!
Is it possible to assign something like scale_colour_hue() to each geom_line, or is this only possible for the ggplot?
Thanks!
As I outlined above, here are some options:
df <- data.frame("letter"=c(rep("a",5),rep("b",5)),
"x"=rep(seq(1,5),2),
"y1"=c(seq(6,10),seq(6,10)/2),
"y2"=c(seq(1,5),seq(1,5)/2),
"y3"=c(seq(3,7),seq(3,7)/2))
# melt your data and create a grouping variable
library(plyr)
df_m <- melt(df,id.vars = 1:2)
df_m$grp <- with(df_m,interaction(letter,variable))
# Option 1
ggplot(df_m,aes(x = x, y = value)) +
facet_wrap(~variable) +
geom_line(aes(group = letter,colour = letter))
# Option 2
ggplot(df_m,aes(x = x, y = value)) +
geom_line(aes(group = grp,colour = letter,linetype = variable))

Resources