Add multiple curves / functions to one ggplot through looping
The issue is that all the stat_function
s you are refer to the same i
variable. And as a consequence, each function you add will overlay perfectly with the others.
The solution is to reassign the variable in a local scope, to make a local copy for each iteration:
p1 = ggplot(data.frame(x = 1 : 200)) + aes(x)
for (i in 1:10){
p1 = local({
j = i
p1 + stat_function(fun = function(x) x + j * 3, col = j)
})
}
To make matters more confusing, you don’t actually have to give the local variable a new name; you could just as easily have written i = i
, and continued to use i
. The reason is that this assignment will generate a new local variable i
that masks the non-local variable i
. I hope we can agree that writing such code is confusing, and a bad idea.
I’ve also taken the liberty of simplifying your code slightly by moving the data x
out of the stat_function
, and into the ggplot
object directly.
However, it is altogether cleaner not to use a loop and reassignment here. Instead you can use lapply
or map
(from the purrr package):
p1 = ggplot(data.frame(x = 1 : 200)) +
aes(x) +
map(
1 : 10,
~ stat_function(fun = function (x) x + .x * 3, color = .x)
)
This is shorter, more readable (it focuses on the “what” rather than the “how”, i.e. the mechanics of the loop), and it uses a single assignment.
Using for loop to create multiple graphs with ggplot in R
This makes a plot for each "Criteria"
library(tidyverse)
sample_df <- data.frame(
stringsAsFactors = FALSE,
check.names = FALSE,
Criteria = c("A", "B", "C", "D", "E", "F"),
`Person A` = c(10L, 50L, 10L, 15L, 40L, 12L),
`Person B` = c(15L, 55L, 2L, 18L, 25L, 35L),
`Person C` = c(12L, 40L, 5L, 22L, 18L, 10L),
`Person D` = c(11L, 37L, 3L, 30L, 32L, 12L)
)
sample_df %>%
pivot_longer(cols = -Criteria,
names_to = "person",
names_prefix = "Person\\s",
values_to = "n") %>%
group_nest(Criteria) %>%
mutate(plot = map(data, ~ggplot(.x, aes(x = person, y = n)) + geom_col())) %>%
pull(plot)
#> [[1]]
#>
#> [[2]]
#>
#> [[3]]
#>
#> [[4]]
#>
#> [[5]]
#>
#> [[6]]
Created on 2022-02-11 by the reprex package (v2.0.1)
How to generate multiple ggplots using a for loop
Try with this:
library(ggplot2)
#Function does not return graph
for (i in list){
var <- sym(i)
print(ggplot(data = test_df, aes(x= DateTime.lub, y = !!var))+
geom_line(aes(colour = Step))+
ggtitle(paste0('plot_',i)))
}
ggplot2: output multiple plots by looping
Following this answer:
library(ggplot2)
point1 <- c(1,2)
point2 <- c(2,2)
points <-as.data.frame(rbind(point1,point2))
point_plots_list <- vector('list', ncol(points))
point_plots_list <- list()
for (i in 1:nrow(points)) {
message(i)
point_plots_list[[i]] <- local({
i <- i
p <- ggplot(data = points) +
geom_point(aes(x = points[i, 1], y = points[i, 2])) +
xlim(-3, 3) +
ylim(-3, 3) +
theme_bw()
})
}
#> 1
#> 2
point_plots_list
#> [[1]]
#>
#> [[2]]
Using lapply
instead of a for
loop and displaying plots with ggarrange
or multiplot
:
library(ggplot2)
library(ggpubr)
point1 <- c(1, 2)
point2 <- c(2, 2)
points <- as.data.frame(rbind(point1, point2))
plot_data <- function(data) {
ggplot(data) +
geom_point(aes(x = data[, 1], y = data[, 2])) +
xlim(-3, 3) +
ylim(-3, 3) +
theme_bw()
}
myplots <- list()
myplots <- lapply(1:nrow(points), function(i) plot_data(points[i, ]))
ggarrange(myplots[[1]], myplots[[2]],
labels = c("A", "B"),
ncol = 2, nrow = 1)
source("http://peterhaschke.com/Code/multiplot.R") #load multiplot function
multiplot(plotlist = myplots, cols = 2)
#> Loading required package: grid
Created on 2021-04-09 by the reprex package (v0.3.0)
Plotting multiple plots on the same page using ggplot and for loop
i
in the for
loop is the dataset hence res_plot_list[[i]]
fails. Try -
for (i in seq_along(plots_list)) {
res_plot_list[[i]] <- residual_plots(plots_list[[i]])
}
Or why not just use lapply
-
res_plot_list <- lapply(plots_list, residual_plots)
How to create several plots with different names at once (ggplot in a loop)
You can save the plots in a list. Here is a for
loop to do that.
library(ggplot2)
variable_to_be_plotted<-c("a","b","c")
list_plots <- vector('list', length(variable_to_be_plotted))
for (i in seq_along(list_plots)) {
list_plots[[i]] <- ggplot(data = mydata,
aes(.data[[variable_to_be_plotted[i]]])) + geom_boxplot()
}
Individual plots can be accessed via list_plots[[1]]
, list_plots[[2]]
etc.
how to add layers in ggplot using a for-loop
One approach would be to reshape your data frame from wide format to long format using function melt()
from library reshape2
. In new data frame you will have x1
values, variable
that determine from which column data came, and value
that contains all original y values.
Now you can plot all data with one ggplot()
and geom_line()
call and use variable
to have for example separate color for each line.
library(reshape2)
df.long<-melt(df,id.vars="x1")
head(df.long)
x1 variable value
1 1 y1 2.0
2 2 y1 5.4
3 3 y1 7.1
4 4 y1 4.6
5 5 y1 5.0
6 1 y2 0.4
ggplot(df.long,aes(x1,value,color=variable))+geom_line()
If you really want to use for() loop (not the best way) then you should use names(df)[-1]
instead of seq()
. This will make vector of column names (except first column). Then inside geom_line()
use aes_string(y=i)
to select column by their name.
plotAllLayers<-function(df){
p<-ggplot(data=df,aes(df[,1]))
for(i in names(df)[-1]){
p<-p+geom_line(aes_string(y=i))
}
return(p)
}
plotAllLayers(df)
Can I plot multiple function curves in a single plot using ggplot() in a user-defined function?
1) Add an i
argument to the function and specify it in args=
like this:
library(ggplot2)
plot_func1 <- function(i) {
p <- ggplot() + xlim(0,i) + xlab("x")
for (i in 1:i) {
p <- p +
geom_function(fun = function(x, i) i*x, args = list(i = i))
}
print(p)
}
plot_func1(4)
2) or use bquote
:
library(ggplot2)
plot_func2 <- function(i) {
p <- ggplot() + xlim(0,i) + xlab("x")
for (i in 1:i) {
p <- p + geom_function(fun = bquote(function(x) .(i)*x))
}
print(p)
}
plot_func2(4)
3) or substitute i into the function like this:
library(ggplot2)
plot_func3 <- function(i) {
p <- ggplot() + xlim(0,i) + xlab("x")
for (i in 1:i) {
p <- p + geom_function(fun = substitute(function(x) i*x, list(i = i)))
}
print(p)
}
plot_func3(4)
4) or define the function as a character string with i substituted in and then parse it and convert it to a call object using [[1]]:
library(ggplot2)
plot_func4 <- function(i) {
p <- ggplot() + xlim(0,i) + xlab("x")
for (i in 1:i) {
p <- p +
geom_function(fun = parse(text = sprintf("function(x) %d*x", i))[[1]])
}
print(p)
}
plot_func4(4)
Related Topics
How to Read Column Names 'As Is' from CSV File
How to Log Transform the Y-Axis of R Geom_Histogram in the Right Direction
Generating a Date from a String with a 'Month-Year' Format
How to Add a Legend for the Secondary Axis Ggplot
Filtering a Dataframe Showing Only Duplicates
Select N Rows Above and Below Match
Chi Square Test for Each Row in Data Frame
Changing Line Color in Ggplot Based on Slope
In R Data.Frame, Promote Rownames to Actual Column
In R, Switch Uppercase to Lowercase and Vice-Versa in a String
Display Selected Folder Path in Shiny
Converting Multiple Existing Xts Objects to Multiple Data.Frames
Group Values by Unique Elements