Is it possible to have something like this in R?
plotFunction <- function(gradientCols(x,y)){
p <- ggplot(diamonds, aes(carat, price)) +
scale_fill_gradient(low = x, high = y) +
geom_bin2d()
return(p)
}
plotFunction(gradientCols("red","blue"))
Where the argument gradientCols in the function plotFunction can take 2 additional arguments (i.e., x,y)?
Or is there a better way to do this without having to explicitly state all the individual arguments in the function?
Here, we just pass the 'x' and 'y'
library(ggplot2)
plotFunction <- function(x, y){
ggplot(diamonds, aes(carat, price)) +
scale_fill_gradient(low = x, high = y) +
geom_bin2d()};
plotFunction("red", "blue")
Related
In my ggplot below, I'm trying to change the 10 facet labels of facet_wrap using labeller(sch.id=paste0("sch.id:", unique(ten$sch.id))).
However, the plot shows NA instead of the correct facet labels, I wonder what the fix is?
library(ggplot2)
hsb <- read.csv('https://raw.githubusercontent.com/rnorouzian/e/master/hsb.csv')
ten <- subset(hsb, sch.id %in% unique(sch.id)[1:10])
p <- ten %>% ggplot() + aes(ses, math) + geom_point() +
facet_wrap(~sch.id) + geom_smooth(method = "lm", se = FALSE)
p + facet_wrap(~sch.id, labeller = labeller(sch.id=paste0("sch.id:", unique(ten$sch.id)))) ## HERE ##
The problem seems to be that you are passing a variable to the labeller function but facet_wrap already passes its own faceting variable. A conflict occurs and the result are NA's.
The solution is to create a labeller function as a function of a variable x (or any other name as long as it's not the faceting variables' names) and then coerce to labeller with as_labeller.
Note that there is no need for unique, just like there is no need for it in the facet_wrap formula.
p <- ten %>% ggplot() + aes(ses, math) + geom_point() +
geom_smooth(method = "lm", formula = y ~ x, se = FALSE)
cust_labeller <- function(x) paste0("sch.id:", x)
p + facet_wrap(~ sch.id,
labeller = as_labeller(cust_labeller)) ## HERE ##
I think the easiest way would be to change sch.id before plotting.
library(ggplot2)
ten$sch.id <- paste0("sch.id:", ten$sch.id)
ggplot(ten) + aes(ses, math) +
geom_point() +
geom_smooth(method = "lm", se = FALSE) +
facet_wrap(~sch.id)
If you don't want to modify your data and want to use the labeller argument you can create a named vector and use it in labeller.
cust_label <- setNames(paste0("sch.id:", unique(ten$sch.id)), unique(ten$sch.id))
ggplot(ten) + aes(ses, math) +
geom_point() +
geom_smooth(method = "lm", se = FALSE) +
facet_wrap(~sch.id, labeller = as_labeller(cust_label))
Instead of 'log2', I want to use 'log2/(log2-1)'
sp <- ggplot(cars, aes(x = speed, y = dist)) + geom_point()
sp
sp + scale_x_continuous(trans='log2') +
scale_y_continuous(trans='log2')
When I try, I get:
object 'log2/(log2-1)_trans' of mode 'function' was not found
Thanks.
You have to define the function first, and its inverse for the labelling, then use the trans_new function from the scales package:
log2_1 <- function(x) log2(x)/(log2(x)-1)
antilog2_1 <- function(x) 2^(x/(x-1))
sp + scale_x_continuous(trans = trans_new("log2_1",
transform=log2_1,
inverse=antilog2_1)) +
scale_y_continuous(trans = trans_new("log2_1",
transform=log2_1,
inverse=antilog2_1))
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)
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)
}
I am trying to write a function in ggplot2 and obtain this error message:
Error in layout_base(data, vars, drop = drop) :
At least one layer must contain all variables used for facetting
Here is my code:
growth.plot<-function(data,x,y,fac){
gp <- ggplot(data = data,aes(x = x, y = y))
gp <- gp + geom_point() + facet_wrap(~ fac)
return(gp)
}
growth.plot(data=mydata, x=x.var, y=y.var,fac= fac.var)
If I try without the function, the plot appears perfectly
gp1 <- ggplot(data = mydata,aes(x = x.var), y = y.var))
gp1+ geom_point()+ facet_wrap(~ fac.var) # this works
Here is reproducible solution where your x, y, and fac arguments must be passed as character:
library(ggplot2)
make_plot = function(data, x, y, fac) {
p = ggplot(data, aes_string(x=x, y=y, colour=fac)) +
geom_point(size=3) +
facet_wrap(as.formula(paste("~", fac)))
return(p)
}
p = make_plot(iris, x="Sepal.Length", y="Petal.Length", fac="Species")
ggsave("iris_plot.png", plot=p, height=4, width=8, dpi=120)
Thanks to commenters #Roland and #aosmith for pointing the way to this solution.