List of plots using lapply
There are problems with lazy evaluation, or something like it anyway. You need to do the following:
ll<-lapply(
seq(1,5),
function(i) qplot(data=data.frame(y=df[, i]), df1, y)
)
This will force the y values to be updated for each plot.
More discussion in this other SO Post.
Using apply function on a list to get plots
A reproducible example would have been helpful.
You should calculate the stats and plot in the same lapply
code, however you don't need to recalculate the stats since you already have it in stats1
. split
stats1
based on Group
and use that data to plot.
library(ggplot2)
splitlist = split(stats1,stats1$Group)
lapply(splitlist,function(x) {
ggplot(data=x, aes(ERF,mean)) +
geom_bar(stat="identity",position="dodge")+
geom_errorbar(aes(ymin = mean - sem, ymax = mean + sem), width = 0.2)
}) -> list_plots
list_plots
lapply on a list of dataframe to create plots
As you used dplyr
pipe, the first argument of ggplot()
is already filled, leading df
to be understood as aes
argument.
box <- function(df){
df %>%
ggplot(aes(x = df[,4], y = df[,2])) +
geom_boxplot() +
ggtitle(g)
}
Create different types of plots within list of plot objects created with lapply
Instead of putting everything inside one function you could
make use separate functions for each plot type along the lines of your first
make_plots
function.make a wrapper for the outer loop which calls the plot type functions were I make use of
purrr::imap
instead of lapply to pass the name of the plot type.
Note: I dropped the log type and just illustrate the approach with a scatter and bar chart.
library(ggplot2)
library(dplyr)
library(purrr)
mtcars2 <- mtcars %>%
dplyr::mutate(plot_type = case_when(
gear == 3 ~ "scatter",
gear %in% c(4, 5) ~ "bar"
))
make_scatter <- function(data) {
lapply(sort(unique(data$gear)), function(i) {
ggplot2::ggplot(data[data$gear == i, ], ggplot2::aes(x = wt, y = mpg, color = factor(cyl))) +
ggplot2::geom_point() +
ggplot2::facet_wrap(~gear) +
ggplot2::scale_color_discrete(name = "cyl")
})
}
make_bar <- function(data) {
lapply(sort(unique(data$gear)), function(i) {
ggplot2::ggplot(data[data$gear == i, ], ggplot2::aes(x = cyl, fill = factor(cyl))) +
ggplot2::geom_bar() +
ggplot2::facet_wrap(~gear) +
ggplot2::scale_color_discrete(name = "cyl")
})
}
make_plots <- function(data) {
split_data <- split(data, data$plot_type)
p_type <- purrr::imap(split_data, function(x, plot_type) {
if (plot_type == "scatter") {
make_scatter(x)
} else if (plot_type == "bar") {
make_bar(x)
}
})
p_type
}
make_plots(mtcars2)
#> $bar
#> $bar[[1]]
#>
#> $bar[[2]]
#>
#>
#> $scatter
#> $scatter[[1]]
Using lapply to make a plot with factors from a list of data frames
When you use lapply
to loop through a list, the argument passed to the function is the element of the list not the index, so you can not use abc_list[[x]]
to subset instead, just use x
, so for your case:
par(mfrow = c(1, 3))
lapply(abc_list, function(x) {plot(x$q, x$value, col = x$factor2)})
There is another convenient way to get this kind of plot using ggplot2
package with facet_grid
, where you don't need to split your original data frame into lists but specify the factor1
as a variable to layout your plots:
library(ggplot2)
ggplot(abc.df, aes(x = q, y = value, col = factor2)) + geom_point() + facet_grid(.~factor1)
Saving plots generated from list using names in list using lapply
The problem with your code is that when you apply your function to each data.frame
in your list
then names(input)
gives you the column names of the data.frame
. See this example.
data(mtcars)
l = list()
l$a = mtcars[, 1:2]
l$b = mtcars[, 2:3]
lapply(l, names)
$a
[1] "mpg" "cyl"
$b
[1] "cyl" "disp"
To resolve this change the function to take a second argument name.
volc = function(input, name) {
ggplot(input, aes(logFC, negLogPval)) +
geom_point()
ggsave(paste0("Volcano_", name, ".png"), device = "png")
}
Now you can use Map
to archieve your goal:
Map(volc, list, names(list))
lapply function to create many plots in Ggplot
you can adapt this to your data strucutre:
plot_data_column = function (.data, .column) {
ggplot2::ggplot(data= .data, ggplot2::aes(y=!!dplyr::sym(.column),x = Petal.Width)) +
ggplot2::geom_line() +
ggplot2::geom_hline(yintercept = .data %>%
dplyr::pull(!!dplyr::sym(.column)) %>%
mean(),
color="red")+
ggplot2::ggtitle(.column) +
ggplot2::theme_minimal()
}
plots <- names(iris)[1:3] %>%
purrr::map(~plot_data_column(.data = iris, .column = .x))
You need to change the names(iris)[1:3]
to your names names(excess_return)[1:10]
and x = Petal.Width
to x = date
.
Use lapply to plot data in a list and use names of list elements as plot titles
One possibility would be to loop over the names
of the list:
lapply(names(comp.surv), function(x) plot(comp.surv[[x]], main = x))
Or slightly more verbose, loop over the list indices:
lapply(seq_along(comp.surv), function(x) plot(comp.surv[[x]], main = names(comp.surv)[x]))
list of dataframes to a list of plots; for loops, lapply
The following code is the question's code corrected. It outputs a list with 5 members, each a list with 3 plots.
aplotfinal <- lapply(1:length(Rlist),function(i){
a <- Rlist[[i]][,-1]
lapply(colnames(a), function(t){
del <- 0.016667
x.spec <- spectrum(a[[t]], log = "no", plot = FALSE)
spx <- x.spec$freq/del
spy <- 2*x.spec$spec
qplot(y = spy,x=spx,geom="line") +
ggtitle(names(Rlist)[i]) +
xlab("frequency")+ylab("spectral density")
})
})
To see the first plot of the first sub-list:
aplotfinal[[1]][[1]]
creating multiple plots for each file within lapply
Here is a mostly didactic example with dev.set
, which I have run in a new R process without any open graphics devices:
## Report active device
dev.cur()
## null device
## 1
## Open device 2 and make it the active device
pdf("bar.pdf")
## Open device 3 and make it the active device
pdf("foo.pdf")
## List all open devices
dev.list()
## pdf pdf
## 2 3
f <- function() {
## Plot in device 3
plot(1:10, 1:10, main = "foo")
## Cycle to device 2
dev.set()
## Plot in device 2
plot(rnorm(10L), rnorm(10L), main = "bar")
## Cycle to device 3
dev.set()
invisible(NULL)
}
## Call 'f' four times
replicate(4L, f())
## Close device 3 and report active device
dev.off()
## pdf
## 2
## Close device 2 and report active device
dev.off()
## null device
## 1
## Clean up
unlink(c("foo.pdf", "bar.pdf"))
@Limey's suggestion is to work in one device at a time to avoid the bookkeeping required by dev.set
:
pdf("foo.pdf")
f1 <- function() {
plot(1:10, 1:10, main = "foo")
invisible(NULL)
}
replicate(4L, f1())
dev.off()
pdf("bar.pdf")
f2 <- function() {
plot(rnorm(10L), rnorm(10L), main = "bar")
invisible(NULL)
}
replicate(4L, f2())
dev.off()
unlink(c("foo.pdf", "bar.pdf"))
Related Topics
R: Split Elements of a List into Sublists
How to Put a Box and Its Label in the Same Row? (Shiny Package)
How to Make an Overlapping Barplot
Extract Time Series of a Point ( Lon, Lat) from Netcdf in R
Combined Line & Bar Geoms: How to Generate Proper Legend
Filter Dataframe by Maximum Values in Each Group
Convert Xml_Nodeset to Data.Frame
How to Increase the Resolution of My Plot in R
Index Element from List in Rcpp
Using Mean with .Sd and .Sdcols in Data.Table
Warning: Unable to Access Index for Repository Https://Www.Stats.Ox.Ac.Uk/Pub/Rwin/Src/Contrib:
How to Reset All Options() Arguments to Their Default Values
How to Pass the "..." Parameters in the Parent Function to Its Two Children Functions in R
Adding Scale Bar to Ggplot Map
How to Make Scatterplot Points Open a Hyperlink Using Ggplotly - R
Different Font Faces and Sizes Within Label Text Entries in Ggplot2
Combine Lists While Overriding Values with Same Name in R
How Can a Script Find Itself in R Running from the Command Line