I can't seem to find a way to combine two ggplots having different function ranges.
library(ggplot2)
myfun <- function(x) {
1/(1 + exp(-x))}
ggplot( NULL,aes(x)) +
stat_function(data=data.frame(x=c(0, 20)),fun=myfun, geom="line") +
stat_function(data=data.frame(x=c(10, 20)),fun=1/myfun, geom="line")
EDIT: Had a mistake in the question: 1/myfunc instead of myfunc in the second function data.
I am not sure if this is what you want, but I give your function two different colors based on two ranges. You can use the following code:
library(ggplot2)
myfun <- function(x) {
1/(1 + exp(-x))}
ggplot(NULL) +
stat_function(data= data.frame(x = c(0, 10)), aes(x, color = "blue"), fun=myfun, xlim = c(0,10)) +
stat_function(data= data.frame(x = c(10, 20)), aes(x, color = "red"), fun=myfun, xlim = c(10,20)) +
scale_color_manual(labels = c("blue", "red"), values = c("blue", "red"))
Output:
As you can see in the plot, the function is plotted within two different ranges.
Answer to edited question
I would suggest to just make a second function like this:
library(ggplot2)
myfun1 <- function(x) {
1/(1 + exp(-x))}
myfun2 <- function(x) {
1/(1/(1 + exp(-x)))}
ggplot( NULL) +
stat_function(data=data.frame(x=c(0, 20)),fun=myfun1, geom="line") +
stat_function(data=data.frame(x=c(10, 20)),fun=myfun2, geom="line")
Output:
Related
currently I am trying to making a plot list with ggplot from a list of data frames (94 time series). Then I want to export the plots to a PDF. This, so far, was successful using following code:
plot.list = lapply(HR_clean, function(x) {
y = length(x)
z = data.frame("HR" = x, "Time" = rep(1:y, 1))
ggplot(z, aes(x = Time, y = HR)) +
theme_bw() +
geom_line(linetype = "solid") +
ggtitle("Plot Title")
})
ggsave(
filename = "plots2.pdf",
plot = marrangeGrob(plot.list, nrow=1, ncol=1),
width = 15, height = 9
)
However, I also want that the main title of each plot is equal name of the corresponding list object. Perhaps anyone knows a smart solution for this problem.
Best,
Johnson
I couldn't test this (since you are not providing example data) but this should work using purrr's imap():
plot.list <- purrr::imap(HR_clean, function(x, name) {
y <- length(x)
z <- data.frame("HR" = x, "Time" = rep(1:y, 1))
ggplot(z, aes(x = Time, y = HR)) +
theme_bw() +
geom_line(linetype = "solid") +
ggtitle(name)
})
I am trying to create some ggplots automaticly. Here is my working code example for adding stat_functions:
require(ggplot2)
p1 <- ggplot(data.frame(x = c(-2.5, 7.5)), aes(x = x)) + theme_minimal()+
stat_function(fun= function(x){1*x},lwd=1.25, colour = "navyblue") +
stat_function(fun= function(x){2*x},lwd=1.25, colour = "navyblue") +
stat_function(fun= function(x){3*-x},lwd=1.25, colour = "red")
p1
As you can see the stat_functions all use (nearly) the same function just with a different parameter.
Here is what i have tried to write:
f <- function(plot,list){
for (i in 1:length(list)){
plot <- plot + stat_function(fun= function(x){x*list[i]})
}
return(plot)
}
p1 <- ggplot(data.frame(x = c(-2.5, 7.5)), aes(x = x)) + theme_minimal()
p2 <- f(p1,c(1,2,3))
p2
This however doesnt return 3 lines, but only one. Why?
Your question is a bit confusing, because the first plot actually contains some other variable bits, but in your function you have a single stat_summary call for only one variable element.
Anyways. Keep the ggplot main object separate and create a list of additional objects, very easy for example with lapply. Add this list to your main plot as usual.
Check also https://ggplot2-book.org/programming.html
library(ggplot2)
p <- ggplot(data.frame(x = c(-2.5, 7.5)), aes(x = x)) + theme_minimal()
ls_sumfun <- lapply(1:3, function(y){
stat_function(fun= function(x){y*x}, lwd=1.25, colour = "navyblue")
}
)
p + ls_sumfun
Created on 2021-04-26 by the reprex package (v2.0.0)
In R, you can pass functions as arguments. You can also return functions from functions. This might make your code simpler and cleaner.
Here's an example:
p1 <- ggplot(data.frame(x = c(-2.5, 7.5)), aes(x = x))
add_stat_fun <- function (ggp, f) {
ggp + stat_function(fun = f)
}
make_multiply_fun <- function (multiplier) {
force(multiplier) # not sure if this is required...
f <- function (x) {multiplier * x}
return(f)
}
my_funs <- lapply(1:3, make_multiply_fun)
# my_funs is now a list of functions
add_stat_fun(p1, my_funs[[1]])
add_stat_fun(p1, my_funs[[2]])
add_stat_fun(p1, my_funs[[3]])
I'm trying to create a utility function that combines several geom_, like in this example (which doesn't work):
my_geom_y <- function(yy, colour){
geom_line(aes(y=yy), col=colour) + geom_point(aes(y=yy), col=colour)
}
so that then I can do this:
myX <- 0:90
ggplot(mapping = aes(x=myX)) + my_geom_y(dlnorm(myX), "red") + my_geom_y(dexp(myX), "blue")
Is that possible?
I tried using get(), eval(), substitute(), as.name() with no avail.
Looking at related posts: passing parameters to ggplot, Use of ggplot() within another function in R didn't help.
I like MSM's approach, but if you want to be able to add my_geom_y to a ggplot you've already made, this is an alternative that might suit what you're after:
library(ggplot2)
x <- 1:100
my_geom_y <- function(yy, colour = "black"){
list(
geom_line(mapping = aes(y= yy),
col = colour),
data = data.frame(x, yy)),
geom_point(mapping = aes(y = yy),
col = colour,
data = data.frame(x, yy))
)
}
ggplot(mapping = aes(x)) +
my_geom_y(x, "red") +
my_geom_y(dlnorm(x), "blue") +
my_geom_y((x^1.1), "black") +
my_geom_y(x/2, "yellow")
I don't have enough reputations to comment so here is a suggestion:
my_geom_y <- function(xx, yy, colour){
ggplot() +
geom_line(aes(x=xx, y=yy), col=colour) +
geom_point(aes(x=xx, y=yy), col=colour)
}
This will create one plot. To create multiple ones, you need to pass your inputs to the function as a list and loop through it inside the function for each geom (since we can't add two or more ggplot objects) - if that makes sense.
Based on #luke-c idea, this makes the function standalone, cut-n-paste ready. We can also add now labels to each curve.
my_geom_y <- function(.xx, .yy, yLabel = 1, .colour=NA ){
if (is.na(.colour))
.colour <- palette()[yLabel%%length(palette())]
list( geom_line(mapping=aes(.xx,.yy), col=.colour, data=data.frame(.xx, .yy)),
geom_point(mapping=aes(.xx,.yy), col=.colour, data=data.frame(.xx, .yy)),
annotate(geom="text" , col = .colour, label=deparse(substitute(.yy)),
x=mean(.xx),y=max(.yy)-(max(.yy)-min(.yy))/20*yLabel)
)
}
myX <- 1:10
ggplot() + my_geom_y(myX, dlnorm(myX), 1) +
my_geom_y(myX, dexp(myX), 2) + my_geom_y(myX, dexp(myX,0.7), 3)
This function becomes handy when you need to visually compare multiple distributions.
I'm working with this function here:
library(ggplot2)
getp1 <- function(names, data, colors) {
num_lines <- length(names)
p1_colors <- colors
names(p1_colors) <- names
p1 <- ggplot(data.frame(x = c(0,720)), aes(x)) +
stat_function(fun=data[[1]], geom="line", aes(colour=names[1]), size=1) +
stat_function(fun=data[[2]], geom="line", aes(colour=names[2])) +
stat_function(fun=data[[3]], geom="line", aes(colour=names[3])) +
stat_function(fun=data[[4]], geom="line", aes(colour=names[4])) +
scale_x_continuous(name="") + scale_y_continuous(name="") +
scale_colour_manual(name = "", guide = FALSE, values = p1_colors)
return(p1)
}
Right now, I get four data lines from this. But I want it to plot exactly num_lines lines, so I guess I need to find some way to "copy" the stat_function() bit num_lines times. Any idea how I can do that?
Completely fail to see the purpose of this and may have misunderstood the question. But I think that you can just use lapply to achieve what you want.
library(ggplot2)
# your version, changed so it works for me...
# (may already be something else than you expected?)
getp1_old <- function(names, data, colors) {
p1 <- ggplot(data.frame(x = c(0,720)), aes(x)) +
stat_function(fun=data[[1]], geom="line", colour=colors[1], size=1) +
stat_function(fun=data[[2]], geom="line", colour=colors[2]) +
stat_function(fun=data[[3]], geom="line", colour=colors[3]) +
stat_function(fun=data[[4]], geom="line", colour=colors[4]) +
scale_x_continuous(name="") + scale_y_continuous(name="") +
scale_colour_manual(guide = FALSE, values = colors)
return(p1)
}
# my version, with lapply
getp1_new <- function(names, data, colors) {
num_lines <- length(names)
stat_fct_combine <- lapply(1:num_lines, function(index){
stat_function(fun=data[[index]], geom="line", colour=colors[index])
})
p1 <- ggplot(data.frame(x = c(0,720)), aes(x)) +
stat_fct_combine +
scale_x_continuous(name="") +
scale_y_continuous(name="") +
scale_colour_manual(guide = FALSE, values = colors)
return(p1)
}
# reproducible example
nms <- paste0('nr', 1:6)
dta <- list(function(x) 1, function(x) 2, function(x) 3, function(x) 4,
function(x) 5, function(x) 6)
cols <- rep(c('red', 'green', 'black', 'blue'), length=6)
# example plots
getp1_old(nms, dta, cols)
getp1_new(nms[1:4], dta, cols)
getp1_new(nms, dta, cols)
I want to plot y=log(1+x) and y=x in the range [-0.25, 0.25]. Here is my code so far -
library(ggplot2)
log1plusx <- function(x) log(1+x)
self <- function(x) x
ggplot(data.frame(x=c(-0.25, 0.25)), aes(x=x)) + stat_function(fun=log1plusx, color="red") + stat_function(fun=self, color="blue")
I can't figure out how to add the legends for these two lines. Tried using guide_legend, but nothing works so far.
Any ideas?
Partial answer:
ggplot(data.frame(x=c(-0.25, 0.25)), aes(x=x)) +
geom_path(aes(colour="red"), stat="function", fun=log1plusx)+
geom_path(aes(colour="blue"), stat="function", fun=self) +
scale_colour_identity("Function", guide="legend",
labels = c("log1plusx", "self"),
breaks = c("red", "blue"))
Though in my opinion you'll be better off building a data.frame before plotting.
Here is how I solved it. Other ideas are welcome.
log1plusx <- function(x) log(1+x)
self <- function(x) x
plot.range1 <- data.frame(x=c(-0.25, 0.25), Functions = factor(1))
plot.range2 <- data.frame(x=c(-0.25, 0.25), Functions = factor(2))
ggplot(NULL, aes(x=x, colour=Functions)) +
stat_function(data = plot.range1, fun = log1plusx) +
stat_function(data = plot.range2, fun = self) +
scale_colour_manual(values = c("red", "green"), labels = c("log(1+x)", "x")) +
theme(axis.title.y=element_blank())