List of Plots Using Lapply

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

  1. make use separate functions for each plot type along the lines of your first make_plots function.

  2. 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]]

Sample Image

#> 
#> $bar[[2]]

Sample Image

#> 
#>
#> $scatter
#> $scatter[[1]]

Sample Image

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)})

Sample Image

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)

Sample Image

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]]

Sample Image

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



Leave a reply



Submit