Reputation: 27
I am trying to filter and plot 11 different graphs based on 11 different levels from a column stored in a vector.
For a quick, reproducible example, here's basically something I've tried:
library(dplyr)
library(ggplot)
positions = c("forward", "defense")
df <- data.frame(player = c("Sergio Ramos", "Lionel Messi",
"Dani Alvez", "Christiano Ronaldo"),
position = c("forward", "defense", "defense", "forward"),
goals = c(12, 8, 2, 23))
for (i in 1:length(positions)) {
df %>%
filter(position == positions[i]) %>%
print(ggplot(aes(x = player, y = goals)) +
geom_bar(stat = "identity"))
}
If I just wrap the filter in print()
and run it, I get both subsets:
player position goals
1 Sergio Ramos forward 12
2 Christiano Ronaldo forward 23
player position goals
1 Lionel Messi defense 8
2 Dani Alvez defense 2
But the code above gives me
Error: ggplot2 doesn't know how to deal with data of class uneval.
If I run the code without the loop, it graphs fine.
I want to be able to loop through the variables and publish them all in Rmd or save them all. Can someone explain why the above does not work? Thanks!
Upvotes: 1
Views: 2155
Reputation: 1731
If you want to have all the plots in one place independently (without using facet_wrap), you can try the following:
split the dataframe into groups defined by position as a factor.
dfx <- split(df,as.factor(df$position))
lapply Solution
Also you can use lapply on the splitted dataframe as follows:
define a function that produce the plot you want
my_plot <- function(x){
g <- ggplot(x,aes(x = player, y = goals)) +
geom_bar(stat = "identity")
}
use lapply
ggy <- lapply(dfx,my_plot)
You will have all plots in ggy:
ggy$defense
ggy$forward
for-loop solution
create an empty list to keep all plots in.
ggx <- list()
loop and save each plot in ggx list.
for(i in 1:length(positions)){
# create a barplot and save in g
g <- ggplot(dfx[[i]],aes(x = player, y = goals)) +
geom_bar(stat = "identity")
n <- dfx[[i]]$position %>% unique() %>% as.character()
# add the plot to the list
ggx[[n]] <- g
}
now you have the plots in:
ggx[[1]] or ggx$defense
ggx[[2]] or ggx$forward
You can print wherever you want, save or get information.
> ggx$defense$data
player position goals
2 Lionel Messi defense 8
3 Dani Alvez defense 2
Upvotes: 2
Reputation: 51622
You don't really need any kind of loop to get what you need. The facet_wrap
can do what you need. i.e.
ggplot(df, aes(x = player, y = goals)) + geom_bar(stat = 'identity') +facet_wrap(~position)
Upvotes: 2
Reputation: 415
The below will save a plot to each page of a pdf in your working directory
pdf("out.pdf", width = 7, height = 7)
for (i in 1:length(positions)) {
print( df %>%
filter(position == positions[i]) %>%
ggplot(aes(x = player, y = goals)) +
geom_bar(stat = "identity"))
}
dev.off()
For markdown documents start with the markdown cheat sheet here.
However I think you may want to look into using the facet_grid
or facet_wrap
function and saving that to pdf in the same method as above
Upvotes: 1
Reputation: 4416
You could do it this way too:
for (i in positions) {
dfplt <- df %>%
filter(position == positions)
plt <- ggplot(dfplt,aes(x = player, y = goals)) +
geom_bar(stat = "identity")
ggsave(plt, file=paste0(i,"_plot.png"))
}
Upvotes: 0
Reputation: 709
Using the dplyr pipes puts the data frame in wrong place. Try like this instead:
library(dplyr)
library(ggplot2)
positions = c("forward", "defense")
df <- data.frame(player = c("Sergio Ramos", "Lionel Messi",
"Dani Alvez", "Christiano Ronaldo"),
position = c("forward", "defense", "defense", "forward"),
goals = c(12, 8, 2, 23))
for (i in 1:length(positions)) {
df %>%
filter(position == positions[i]) %>%
ggplot(aes(x = player, y = goals)) +
geom_bar(stat = "identity") -> g
print(g)
}
You may also consider rewriting the loop with lapply.
Upvotes: 5