I want to plot some diagrams beside each other (e.g. in columns) and write them to one png file. In graphics::plot it works with layout(...), but how do I arrange diagrams in ggplot2?
Is there something I can do with facets?
Example:
require(cars)
require(data.table)
require(tidyr)
df <- as.data.table(mtcars)
df$obs <- seq_len(df[,.N])
df <- as.data.table(pivot_longer(data = df, names_to = "name", values_to = "val", cols = names(df[, !"obs"])))
df[, name := as.factor(name)]
library(ggplot2)
g <- ggplot(data = df)
g <- g + aes(x = df[, obs], y = df[, val])
g + facet_wrap(df[, name]) + geom_line()
It is not perfect. This gives me a matrix of diagrams for all properties of mtcars. But the y axis is always set to the maximum of the largest value of all properties.
I want the y axis to have the optimum range for each property.
Another thing is, how to plot different tables in the same file:
df1 <- as.data.table(mtcars)[, 1]
df1$obs <- seq_len(df1[,.N])
df2 <- as.data.table(mtcars)[, 2]
df2$obs <- seq_len(df2[,.N])
g1 <- ggplot(data = df1)
g1 <- g1 + aes(x = df1[, obs], y = df1[, mpg])
g1 + geom_line()
g2 <- ggplot(data = df2)
g2 <- g2 + aes(x = df2[, obs], y = df2[, cyl])
g2 + geom_line()
How can I arrange my plots? I don't want them to be plotted in the same diagram. They should have their own axes and titles.
Just free your scale using scales="free" option.
g + facet_wrap(df[, name], scales="free") + geom_line()
For your second question, you may want to consult this answer: Side-by-side plots with ggplot2
Related
(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")
I plot a heatmap using geom_tile (ggplot2):
library("reshape2")
library("ggplot2")
x <- matrix(1:12, nrow=3)
rownames(x) <- LETTERS[1:3]
colnames(x) <- letters[1:4]
x_melted <- melt(x)
x_melted$group1 <- rep(c("T1","T2"), each=6)
ggplot(x_melted, aes(x = Var1, y = Var2)) + geom_tile(aes(fill = value))
But I need add a gap according to group1 in x_melted so that a gap was produced between the first two rows and the last two rows. How could this be added?
One way would be to use facets -
x_melted$group1 = factor(x_melted$group1, levels = c("T2", "T1"))
ggplot(x_melted, aes(x = Var1, y = Var2)) +
geom_tile(aes(fill = value)) +
facet_grid(group1 ~ ., scales = "free_y")
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
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
I'm trying to use ggplot2 to create and label a scatterplot. The variables that I am plotting are both scaled such that the horizontal and the vertical axis are plotted in units of standard deviation (1,2,3,4,...ect from the mean). What I would like to be able to do is label ONLY those elements that are beyond a certain limit of standard deviations from the mean. Ideally, this labeling would be based off of another column of data.
Is there a way to do this?
I've looked through the online manual, but I haven't been able to find anything about defining labels for plotted data.
Help is appreciated!
Thanks!
BEB
Use subsetting:
library(ggplot2)
x <- data.frame(a=1:10, b=rnorm(10))
x$lab <- letters[1:10]
ggplot(data=x, aes(a, b, label=lab)) +
geom_point() +
geom_text(data = subset(x, abs(b) > 0.2), vjust=0)
The labeling can be done in the following way:
library("ggplot2")
x <- data.frame(a=1:10, b=rnorm(10))
x$lab <- rep("", 10) # create empty labels
x$lab[c(1,3,4,5)] <- LETTERS[1:4] # some labels
ggplot(data=x, aes(x=a, y=b, label=lab)) + geom_point() + geom_text(vjust=0)
Subsetting outside of the ggplot function:
library(ggplot2)
set.seed(1)
x <- data.frame(a = 1:10, b = rnorm(10))
x$lab <- letters[1:10]
x$lab[!(abs(x$b) > 0.5)] <- NA
ggplot(data = x, aes(a, b, label = lab)) +
geom_point() +
geom_text(vjust = 0)
Using qplot:
qplot(a, b, data = x, label = lab, geom = c('point','text'))