Select ggtheme randomly - r

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) , "()")))

Related

R plot x and y axes changes

I have my data:
x <- list(10,50,100,250,500,2500)
y <- list(0.09090909,0.01960784,0.003984064,0.003984064,0.001996008,0.0003998401)
I want to link my data to code found on this website
log_c <- seq(-12, 0, by = 0.1)
df <- data.frame(log_c = log_c, response = V(log_c, E, HS, log_EC50))
ggplot(df, aes(log_c, response)) +
geom_line()
I want to put the x data in place of log_c and y data in place of response. These are my beginnings in R, so I am asking for help
At a minimum this will work:
you have expressed your x and y values as lists; it will work better if they are (atomic) vectors (which you would have gotten using c() instead of list()). Put them into a data frame (not strictly necessary, but best practice):
df <- data.frame(x=unlist(x), y = unlist(y))
Use the data frame to draw your plot:
library(ggplot2)
ggplot(df, aes(x, y)) + geom_line()
To get your graph looking a little more like the example in your post,
scalefun <- function(y) (y-min(y))/diff(range(y))
ggplot(df, aes(x, y = scalefun(y))) + geom_line() + scale_x_log10()
Same logic as #Ben Bolker: Just another way:
library(tidyverse)
tibble(x,y) %>%
unnest() %>%
ggplot(aes(x, y))+
geom_line()

using more dataframes in ggplot 2 in 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)

Using ggplot2 in a function [duplicate]

would like to create a function that generates graphs using ggplot. For the sake of simplicity, the typical graph may be
ggplot(car, aes(x=speed, y=dist)) + geom_point()
The function I would like to create is of the type
f <- function(DS, x, y) ggplot(DS, aes(x=x, y=y)) + geom_point()
This however won't work, since x and y are not strings. This problem has been noted in previous SO questions (e.g., this one), but without providing, in my view, a satisfactory answer. How would one modify the function above to make it work with arbitrary data frames?
One solution would be to pass x and y as string names of columns in data frame DS.
f <- function(DS, x, y) {
ggplot(DS, aes_string(x = x, y = y)) + geom_point()
}
And then call the function as:
f(cars, "speed", "dist")
However, it seems that you don't want that? Can you provide an example why you would need different functionality? Is it because you don't want to have the arguments in the same data frame?
I think it's possible the following type of codes, which only build the aes component.
require(ggplot2)
DS <- data.frame(speed=rnorm(10), dist=rnorm(10))
f <- function(DS, x, y, geom, opts=NULL) {
aes <- eval(substitute(aes(x, y),
list(x = substitute(x), y = substitute(y))))
p <- ggplot(DS, aes) + geom + opts
}
p <- f(DS, speed, dist, geom_point())
p
However, it seems to be complicated approach.
Another option is to use do.call. Here is a one line copy paste from a working code:
gg <- gg + geom_rect( do.call(aes, args=list(xmin=xValues-0.5, xmax=xValues+0.5, ymin=yValues, ymax=rep(Inf, length(yValues))) ), alpha=0.2, fill=colors )
One approach that I can think of is using match.call() to reach the variable names contained by the parameters/arguments passed to the custom plotting function and then use eval() on them. In this way you avoid passing them as quoted to your custom function, if you do not like that.
library(ggplot2)
fun <- function(df, x, y) {
arg <- match.call()
ggplot(df, aes(x = eval(arg$x), y = eval(arg$y))) + geom_point()
}
fun(mpg, cty, hwy) # no need to pass the variables (column names) as quoted / as strings

R + ggplot: geom_txt label not recognize a variable in function call

I'm an R/ggplot newbie switching over from MatLab.
I would like to create a function using ggplot with linear regression equation printed on the graph (which is discussed in Adding Regression Line Equation and R2 on graph). But here, I am trying to build a function with it but wasn't successful.
I kept getting an error -
"Error in eval(expr, envir, enclos) : object 'label' not found".
One workaround is to define "label" variable outside of the function but I just don't understand why this doesn't work.
Can anyone explain why?
df <- data.frame(x = c(1:100))
df$y <- 2 + 3 * df$x + rnorm(100, sd = 40)
f <- function(DS, x, y, z) {
label <- z
print(label)
ggplot(DS, aes(x=x, y=y)) +
geom_point() +
labs(y=y) +
labs(title=y) +
xlim(0,5)+
ylim(0,5)+
geom_smooth(method="lm", se=FALSE)+
geom_text (aes(x=1, y=4, label=label))
}
f(df, x, y, "aaa") #execution line
See the following code:
library(ggplot2)
df <- data.frame(x = c(1:100))
df$y <- 2 + 3 * df$x + rnorm(100, sd = 40)
f <- function(DS, x, y, z) {
label.df = data.frame(x=1, y=4, label=z)
ggplot(DS, aes_string(x=x, y=y)) +
geom_point() +
labs(y=y) +
labs(title=y) +
geom_smooth(method="lm", se=FALSE)+
geom_text (aes(x=x, y=y, label=label), label.df)
}
f(df, "x", "y", "aaa")
There were a few fixes about your code:
The data you are using in geom_text is the same you have defined in ggplot() unless you change it. Here I have created a temporary data.frame for this purpose called label.df.
The xlim() and ylim() functions were filtering most of your data points, since the range of x and y are much larger than the limits you defined in the original code.
When you want to pass the names of the columns of your data.frame to be used for displaying the graph it would be easier to pass their names as strings (i.e. "x"). This way, the aes() function is also changed to aes_string().
Here is the result:
Edit
Thanks to #Gregor, a simpler version would be:
f <- function(DS, x, y, z) {
ggplot(DS, aes_string(x=x, y=y)) +
geom_point() +
labs(y=y) +
labs(title=y) +
geom_smooth(method="lm", se=FALSE)+
annotate(geom="text", x=1, y=4, label=z)
}

passing parameters to ggplot

would like to create a function that generates graphs using ggplot. For the sake of simplicity, the typical graph may be
ggplot(car, aes(x=speed, y=dist)) + geom_point()
The function I would like to create is of the type
f <- function(DS, x, y) ggplot(DS, aes(x=x, y=y)) + geom_point()
This however won't work, since x and y are not strings. This problem has been noted in previous SO questions (e.g., this one), but without providing, in my view, a satisfactory answer. How would one modify the function above to make it work with arbitrary data frames?
One solution would be to pass x and y as string names of columns in data frame DS.
f <- function(DS, x, y) {
ggplot(DS, aes_string(x = x, y = y)) + geom_point()
}
And then call the function as:
f(cars, "speed", "dist")
However, it seems that you don't want that? Can you provide an example why you would need different functionality? Is it because you don't want to have the arguments in the same data frame?
I think it's possible the following type of codes, which only build the aes component.
require(ggplot2)
DS <- data.frame(speed=rnorm(10), dist=rnorm(10))
f <- function(DS, x, y, geom, opts=NULL) {
aes <- eval(substitute(aes(x, y),
list(x = substitute(x), y = substitute(y))))
p <- ggplot(DS, aes) + geom + opts
}
p <- f(DS, speed, dist, geom_point())
p
However, it seems to be complicated approach.
Another option is to use do.call. Here is a one line copy paste from a working code:
gg <- gg + geom_rect( do.call(aes, args=list(xmin=xValues-0.5, xmax=xValues+0.5, ymin=yValues, ymax=rep(Inf, length(yValues))) ), alpha=0.2, fill=colors )
One approach that I can think of is using match.call() to reach the variable names contained by the parameters/arguments passed to the custom plotting function and then use eval() on them. In this way you avoid passing them as quoted to your custom function, if you do not like that.
library(ggplot2)
fun <- function(df, x, y) {
arg <- match.call()
ggplot(df, aes(x = eval(arg$x), y = eval(arg$y))) + geom_point()
}
fun(mpg, cty, hwy) # no need to pass the variables (column names) as quoted / as strings

Resources