Plotting two variables using ggplot2 - same x axis - r

I have two graphs with the same x axis - the range of x is 0-5 in both of them.
I would like to combine both of them to one graph and I didn't find a previous example.
Here is what I got:
c <- ggplot(survey, aes(often_post,often_privacy)) + stat_smooth(method="loess")
c <- ggplot(survey, aes(frequent_read,often_privacy)) + stat_smooth(method="loess")
How can I combine them?
The y axis is "often privacy" and in each graph the x axis is "often post" or "frequent read".
I thought I can combine them easily (somehow) because the range is 0-5 in both of them.
Many thanks!

Example code for Ben's solution.
#Sample data
survey <- data.frame(
often_post = runif(10, 0, 5),
frequent_read = 5 * rbeta(10, 1, 1),
often_privacy = sample(10, replace = TRUE)
)
#Reshape the data frame
survey2 <- melt(survey, measure.vars = c("often_post", "frequent_read"))
#Plot using colour as an aesthetic to distinguish lines
(p <- ggplot(survey2, aes(value, often_privacy, colour = variable)) +
geom_point() +
geom_smooth()
)

You can use + to combine other plots on the same ggplot object. For example, to plot points and smoothed lines for both pairs of columns:
ggplot(survey, aes(often_post,often_privacy)) +
geom_point() +
geom_smooth() +
geom_point(aes(frequent_read,often_privacy)) +
geom_smooth(aes(frequent_read,often_privacy))

Try this:
df <- data.frame(x=x_var, y=y1_var, type='y1')
df <- rbind(df, data.frame(x=x_var, y=y2_var, type='y2'))
ggplot(df, aes(x, y, group=type, col=type)) + geom_line()

Related

Violin plots with additional points

Suppose I make a violin plot, with say 10 violins, using the following code:
library(ggplot2)
library(reshape2)
df <- melt(data.frame(matrix(rnorm(500),ncol=10)))
p <- ggplot(df, aes(x = variable, y = value)) +
geom_violin()
p
I can add a dot representing the mean of each variable as follows:
p + stat_summary(fun.y=mean, geom="point", size=2, color="red")
How can I do something similar but for arbitrary points?
For example, if I generate 10 new points, one drawn from each distribution, how could I plot those as dots on the violins?
You can give any function to stat_summary provided it just returns a single value. So one can use the function sample. Put extra arguments such as size, in the fun.args
p + stat_summary(fun.y = "sample", geom = "point", fun.args = list(size = 1))
Assuming your points are qualified using the same group names (i.e., variable), you should be able to define them manually with:
newdf <- group_by(df, variable) %>% sample_n(10)
p + geom_point(data=newdf)
The points can be anything, including static numbers:
newdf <- data.frame(variable = unique(df$variable), value = seq(-2, 2, len=10))
p + geom_point(data=newdf)
I had a similar problem. Code below exemplifies the toy problem - How does one add arbitrary points to a violin plot? - and solution.
## Visualize data set that comes in base R
head(ToothGrowth)
## Make a violin plot with dose variable on x-axis, len variable on y-axis
# Convert dose variable to factor - Important!
ToothGrowth$dose <- as.factor(ToothGrowth$dose)
# Plot
p <- ggplot(ToothGrowth, aes(x=dose, y=len)) +
geom_violin(trim = FALSE) +
geom_boxplot(width=0.1)
# Suppose you want to add 3 blue points
# [0.5, 10], [1,20], [2, 30] to the plot.
# Make a new data frame with these points
# and add them to the plot with geom_point().
TrueVals <- ToothGrowth[1:3,]
TrueVals$len <- c(10,20,30)
# Make dose variable a factor - Important for positioning points correctly!
TrueVals$dose <- as.factor(c(0.5, 1, 2))
# Plot with 3 added blue points
p <- ggplot(ToothGrowth, aes(x=dose, y=len)) +
geom_violin(trim = FALSE) +
geom_boxplot(width=0.1) +
geom_point(data = TrueVals, color = "blue")

Nested facet_wrap() in ggplot2

Say I have these data:
set.seed(100)
mydf<-
data.frame(
day = rep(1:5, each=20),
id = rep(LETTERS[1:4],25),
x = runif(100),
y = sample(1:2,100,T)
)
If I just want to plot all five days of id=="A" using facet_wrap(), we do like this:
ggplot(mydf[mydf$id=="A",], aes(x,y)) +
geom_tile() +
facet_wrap(~day,ncol=1)
Gives:
But, if I want to plot four of these next to each other automatically in a 2x2 grid (i.e. showing A,B,C,D), is that possible using a nested facet? I tried doing multiple variables in the function like this:
ggplot(mydf, aes(x,y)) +
geom_tile() +
facet_wrap(~ day+id)
but this gives this:
I'm looking for a nested approach. Five faceted rows by day in each panel with each plot in columns/rows by id. Obviously for a small number of plots I could save individually and arrange with grid.arrange etc., but in the real data I have many plots so want to automate if possible.
EDIT:
In response to comment - this is the sort of desired output:
try this,
p <- ggplot(mydf, aes(x,y)) +
geom_tile() +
facet_wrap(~ day, ncol=1)
library(plyr)
lp <- dlply(mydf, "id", function(d) p %+% d + ggtitle(unique(d$id)))
library(gridExtra)
grid.arrange(grobs=lp, ncol=2)
Here is a quick attempt using the multiplot function found here
ids = levels(as.factor(mydf$id))
p = vector("list", length(ids))
names(p) = ids
for(i in 1:length(ids)){
p[[i]] = ggplot(mydf[mydf$id == ids[i],], aes(x,y)) + geom_tile() + ggtitle(paste(ids[i])) + facet_wrap(~day, ncol=1)
}
multiplot(p$A, p$B, p$C, p$D, cols = 2)

Axis Labels that are ggplot2 objects / grobs

I wish to use ggplot2 objects/grobs/plots as axis labels.
Here is my toy example:
library(dplyr)
library(ggplot2)
# master plot
df <- data_frame(y = c("unchanging", "increasing", "decreasing"), x = c(20, 50, 30))
ggplot(df, aes(x, y)) + geom_point()
# fxn generates ggplot2 object specifying a line plot from two points
two_pt_line_plot <- function(y1, y2) {
df <- data_frame(y = c(y1, y2), x = c("from", "to"))
ggplot(df, aes(x,y, group = 1)) + geom_line(size = 4) +
xlab(NULL) + ylab(NULL) +
scale_x_discrete(expand=c(0,0)) +
scale_y_continuous(expand=c(0,0))
}
# make the three plot objects, name them appropriately.
grobs <- Map(two_pt_line_plot, c(.5,0,1), c(.5, 1, 0))
names(grobs) <- df$y
grobs
#> $unchanging
#> $increasing
#> $decreasing
I want to programmatically generate this:
The only thing I can currently think of is that I somehow layer over the plots as facets where the theming as been hacked to the max to make it look like it belongs. But I haven't been able to do that yet and it seems like a very hack-y solution. I therefore thought I would throw it out there.

R: Align plots with different x ranges

I have two dataframes dataA and dataB, both of which contain a time and a value column. Time columns are closely related, but non-identical. Now, I generate two plots with ggplot, e.g.:
plotA <- ggplot(dataA) + geom_line(aes(x = time, y = value))
plotB <- ggplot(dataB) + geom_line(aes(x = time, y = value))
How can I use grid.arrange or a similar function to display the two plots vertically and so that x-axis labels and grid lines align?
You could use facets to align the plots.
Firstly, both data sets need to be combined:
dataAB <- rbind(dataA[c("time", "value")], dataB[c("time", "value")])
A new column indicates the original data set:
dataAB$ind <- c(rep("A", nrow(dataA)), rep("B", nrow(dataB)))
Plot:
library(ggplot2)
ggplot(dataAB) +
geom_line(aes(x = time, y = value)) +
facet_wrap( ~ ind, ncol = 1, scales = "free_y")

Create part-fixed, part-free axis limits on facets with ggplot?

I'd like to create a faceted plot using ggplot2 in which the minimum limit of the y axis will be fixed (say at 0) and the maximum limit will be determined by the data in the facet (as it is when scales="free_y". I was hoping that something like the following would work, but no such luck:
library(plyr)
library(ggplot2)
#Create the underlying data
l <- gl(2, 10, 20, labels=letters[1:2])
x <- rep(1:10, 2)
y <- c(runif(10), runif(10)*100)
df <- data.frame(l=l, x=x, y=y)
#Create a separate data frame to define axis limits
dfLim <- ddply(df, .(l), function(y) max(y$y))
names(dfLim)[2] <- "yMax"
dfLim$yMin <- 0
#Create a plot that works, but has totally free scales
p <- ggplot(df, aes(x=x, y=y)) + geom_point() + facet_wrap(~l, scales="free_y")
#Add y limits defined by the limits dataframe
p + ylim(dfLim$yMin, dfLim$yMax)
It's not too surprising to me that this throws an error (length(lims) == 2 is not TRUE) but I can't think of a strategy to get started on this problem.
In your case, either of the following will work:
p + expand_limits(y=0)
p + aes(ymin=0)

Resources