using more dataframes in ggplot 2 in R - r

I get an error when i try to use more than one dataframe in a ggplot2; Error: mapping must be created by aes()
xdf <- data.frame(x=1:3, y=c(18,11,16))
ydf <- data.frame(x=c(5,7), y=c(18,11))
ggplot(xdf, aes(x,y))+
geom_point()+
geom_point(ydf, aes(x,y) )
Is this solvable...?

You need to specify that ydf is the data parameter:
ggplot(xdf, aes(x,y))+
geom_point()+
geom_point(data=ydf, aes(x,y))

Some additional remarks for others who need to work with different data in ggplot2:
If you define aes globally within the function ggplot and you need the same aesthetics, you do not have to write them again.
ggplot(xdf, aes(x, y)) +
geom_point() +
geom_point(data = ydf)
If you need different aesthetics, you can set inherit.aes = FALSE to ignore the global aesthetics.
ggplot(xdf, aes(x, y, color = z)) +
geom_point() +
geom_point(data=ydf, aes(y, x), inherit.aes = FALSE)

Related

Display Greek symbols and charge facet titles at the same time with ggplot

I know how to modify titles in ggplot without altering the original data. Suppose I have the following data frame and I want to change the labels. Then, I would do so in the following way
df <- data.frame(x = 1:4, y = 1:4, label = c(c("params[1]", "params[2]", "params[3]",
"params[4]")))
params_names <- list(
'params[1]'= "beta[11]",
'params[2]'= "beta[22]",
'params[3]'= "beta[33]",
'params[4]'= "beta[44]"
)
param_labeller <- function(variable, value){
params_names[value]
}
ggplot(df, aes(x=x,y=y)) +
geom_point() +
facet_grid(~label, labeller = param_labeller)
If I wanted to display the subscripts, I would just do this
ggplot(df, aes(x=x,y=y)) +
geom_point() +
facet_grid(~label, labeller = label_parsed)
How do I apply both operations at the same time?
I don't know exactly if this conflicts with you not wanting to "alter" the original data, but you add the labelling information to the factor itself:
df$label2 <- factor(df$label,
labels = c("beta[4]", "beta[24]", "beta[42]", "beta[43]"))
ggplot(df, aes(x = x, y = y)) +
geom_point() +
facet_grid( ~ label2, labeller = label_parsed)
This produces the following plot:
Plot with formatted facet labels

Select ggtheme randomly

I would like to draw a ggplot with a random theme (In fact, I want to draw many plots, each with a different theme). Consider the following reproducible example:
# Exmple data
df <- data.frame(x = 1:10, y = 1:10)
# Select theme randomly
random_theme <<- sample(c("theme_gray", "theme_bw", "theme_light", "theme_dark", "theme_minimal", "theme_classic"), 1)
# Draw ggplot
ggplot(df, aes(x, y)) +
geom_line() +
random_theme # This line does not work
Question: How can I select a ggtheme randomly?
Sample from the functions and not the names of the functions. Also, sample returns a list when sampling from anything more complex than a scalar, so you need the first list element. Eg:
> sample(c(sqrt, sqrt),2)
[[1]]
function (x) .Primitive("sqrt")
[[2]]
function (x) .Primitive("sqrt")
So get a random theme function with:
random_theme <- sample(c(theme_gray, theme_bw, theme_light, theme_dark, theme_minimal, theme_classic), 1)[[1]]
and call it when you plot:
ggplot(df, aes(x, y)) +geom_line() + random_theme()
Resample random_theme and plot again to update.
Also, you probably don't need the <<- which I guess is a hangover from desperately trying to make something work...
You could do this with match.fun():
random_theme = match.fun(sample(c("theme_gray", "theme_bw", "theme_light", "theme_dark", "theme_minimal", "theme_classic"), 1))
ggplot(df, aes(x, y)) +
geom_line() +
random_theme()
Sice your random_theme is a character vector, you can use eval and then parse to parse your theme.
library(tidyverse)
ggplot(df, aes(x, y)) +
geom_line() +
eval(parse(text = paste0(random_theme, "()")))
Or more directly:
ggplot(df, aes(x, y)) +
geom_line() +
eval(parse(text = paste0(sample(c("theme_gray",
"theme_bw",
"theme_light",
"theme_dark",
"theme_minimal",
"theme_classic"), 1) , "()")))

Error with facet_grid() when using a function created for plotting

I have created a function for returning a plot in R. There seems to be a issue with facet_grid() that appears when plotting with the created plot function that does not appear when not using the function (even though I use the exact same lines of code).
# function for plotting
barplot_fill <- function(dataset, x, y, fill, jaar) {
p <- ggplot(dataset, aes(x=x, y=y, fill=fill)) +
geom_bar(stat = "identity") +
facet_grid(~ jaar) +
theme_bw() +
scale_y_continuous(labels=comma)
return(p)
}
I would like to plot variables from the following data frame:
df <- data.frame(V1=c(1,2,3,4), V2=c(20,25,46,13), V3=c('a','a','b','b'), V4=c(2018,2019,2018,2017))
When calling the function, I get the following error:
barplot_fill(df, V1, V2, V3, V4)
Error: At least one layer must contain all faceting variables: dataset$jaar.
* Plot is missing dataset$jaar
* Layer 1 is missing dataset$jaar
When I don't call the created function and just create the plot using the ggplot lines of code, R creates the plot and the error does not appear.
ggplot(df, aes(x=V1, y=V2, fill=V3)) +
geom_bar(stat = "identity") +
theme_bw() +
facet_grid(~ V4) +
scale_y_continuous(labels=comma)
I can't figure out why it gives me an error in the created function and why the error does not appear when run the exact same lines of code when not using the function. Can anyone explain me why the error appears when calling the created function?
The problem is that jaar is not evaluated in the facet_grid call, but ggplot is looking for a jaar column in the data set you provide. Actually, something similar happens in the ggplot-call for x, y, and fill if you remove the fact_grid part of the function:
barplot_fill_no_facet <- function(dataset, x, y, fill, jaar) {
p <- ggplot(dataset, aes(x = x, y = y, fill = fill)) +
geom_bar(stat = "identity") +
theme_bw() +
scale_y_continuous()
return(p)
}
barplot_fill_no_facet(df, V1, V2, V3, V4)
Error in FUN(X[[i]], ...) : object 'V1' not found
One solution uses aes_string and formula for facet_grid:
barplot_fill <- function(dataset, x, y, fill, jaar) {
p <- ggplot(dataset, aes_string(x = x, y = y, fill = fill)) +
geom_bar(stat = "identity") +
facet_grid(formula(paste("~", jaar))) +
theme_bw() +
scale_y_continuous()
return(p)
}
barplot_fill(df, "V1", "V2", "V3", "V4")
Apart from a little glitch with scale_y_continuous (you haven't defined comma), the problem is the evaluation of your variables. For aes, you can use aes_string and pass strings, but facet_grid has a different format. See under Variable Facets here.
barplot_fill <- function(dataset, x, y, fill, jaar) {
jaar <- enquo(jaar)
p <- ggplot(dataset, aes_string(x=x, y=y, fill=fill)) +
geom_bar(stat = "identity") +
facet_grid(cols = vars(!!jaar)) +
theme_bw()
return(p)
}
df <- data.frame(V1=c(1,2,3,4), V2=c(20,25,46,13), V3=c('a','a','b','b'), V4=c(2018,2019,2018,2017))
barplot_fill(df, "V1", "V2", "V3", V4)

How to modify ggplot2 legend_text?

I use
geom_point(aes(colour = factor(ClusterID)))
but I want to get ClusterID visible without the word factor.
How can I modify the legend title in ggplot2?
Better to do the factor conversion before plotting. For example using dplyr, assuming data frame mydata and variables x, y:
library(dplyr)
mydata %>%
mutate(ClusterID = factor(ClusterID)) %>%
ggplot(aes(x, y)) + geom_point(aes(color = ClusterID))
Another option is to name the legend in scale_color_discrete:
ggplot(mydata, aes(x, y)) +
geom_point(aes(color = factor(ClusterID))) +
scale_color_discrete(name = "ClusterID")

ggplot: modify coord_cartesian() values dynamically

Is there a way to modify the plot coordinates using coord_cartesian() in a way that is dynamic based on the data in the ggplot call?
For example:
ggplot(cars, aes(x = speed, y = dist)) +
geom_point() +
coord_cartesian(xlim = c(min(.$speed), max(.$speed) + 10))
This doesn't work, nor does using .data$speed.
You can use the magrittr and dplyr pipe operator (%>%) to pass data into the ggplot call.
cars %>%
{ggplot(., aes(speed, dist)) +
geom_point() +
coord_cartesian(xlim = c(min(.$speed), max(.$speed) + 10))
}
Note that now you need to explicitly identify the data argument at the beginning of the ggplot call using the . pronoun.
It's a bit hacky but you can add a blank geom and add 10 to the y in the aesthetics.
ggplot(cars, aes(x = speed, y = dist)) +
geom_point() +
geom_blank(aes(y = dist + 10))

Resources