7

I have a big table of data with ~150 columns. I need to make a series of histograms out of about 1/3rd of them. Rather than putting 50 lines of the same plot command in my script, I want to loop over a list telling me which columns to use. Here is a test dataset to illustrate:

d <- data.frame(c(rep("A",5), rep("B",5)),
                sample(c(1:10), 10, replace=TRUE),     
                sample(c(1:10), 10, replace=TRUE),     
                sample(c(1:10), 10, replace=TRUE),     
                sample(c(1:10), 10, replace=TRUE),     
                sample(c(1:10), 10, replace=TRUE))

colnames(d) <- c("col1","col2","col3","col4","col5","col6" )


ggplot(data=d, aes(col2, fill= col1)) + geom_density(alpha = 0.5)

So, rather than writing this a 50 times and replacing the aes() values, I really want to do something more like this...

cols_to_plot <- c("col2","col4","col6")

for (i in length(cols_to_plot)) {
  ggplot(data=d, aes(cols_to_plot[i], fill= col1)) + geom_density(alpha = 0.5)

} 

But of course, this doesn't work... Is there a way to do this kind of thing?

Thanks!

2

4 Answers 4

10

I think you'd be better off if you melted your data. Try this:

library(reshape2)
d2 <- melt(d, id='col1')
ggplot(d2, aes(value, fill=col1)) + geom_density(alpha=.5) + facet_wrap(~variable)

Or, if you wanted to do what you originally wanted, use aes_string, like:

ggplot(data=d, aes_string(cols_to_plot[i], fill='col1')) + geom_density(alpha = 0.5)
Sign up to request clarification or add additional context in comments.

1 Comment

I am still not sure how to plot only certain columns without using a loop, it should be possible with ggplot, no?
8

Since version 3.0.0 of ggplot2, the aes_string() function has been soft deprecated, with the focus now to use aes().

The trick now is to use the .data object to refer to the data object supplied to ggplot(), which here is d.

Using this, we recover the behviour prior to version 3.0.0 without the soft deprecation wraning:

d <- data.frame(c(rep("A",5), rep("B",5)),
                sample(c(1:10), 10, replace=TRUE),     
                sample(c(1:10), 10, replace=TRUE),     
                sample(c(1:10), 10, replace=TRUE),     
                sample(c(1:10), 10, replace=TRUE),     
                sample(c(1:10), 10, replace=TRUE))

colnames(d) <- c("col1","col2","col3","col4","col5","col6" )

cols_to_plot <- c("col2","col4","col6")

for (i in seq_along(cols_to_plot)) {
  print(ggplot(data = d,
               aes(x = .data[[cols_to_plot[i]]], fill= .data[["col1"]])) +
    geom_density(alpha = 0.5))
}

Original answer using aes_string()

There is an alternative to aes(); aes_string(). With this you can pass in strings for the aesthetic mappings. Note you have to quote col1 here in fill = "col1". Also note that in a for() loop you need to explicitly print() a ggplot object in order for the plot to be drawn on the current device.

d <- data.frame(c(rep("A",5), rep("B",5)),
                sample(c(1:10), 10, replace=TRUE),     
                sample(c(1:10), 10, replace=TRUE),     
                sample(c(1:10), 10, replace=TRUE),     
                sample(c(1:10), 10, replace=TRUE),     
                sample(c(1:10), 10, replace=TRUE))

colnames(d) <- c("col1","col2","col3","col4","col5","col6" )

cols_to_plot <- c("col2","col4","col6")

for (i in seq_along(cols_to_plot)) {
  print(ggplot(data=d, aes_string(x = cols_to_plot[i], fill= "col1")) +
    geom_density(alpha = 0.5))
}

2 Comments

Indeed, this would have had me on a wild goose chase for sure!
For the record: "aes_string() was deprecated in ggplot2 3.0.0. Please use tidy evaluation ideoms [sic] with aes()".
4

Yes, aes_string

cols_to_plot <- c("col2","col4","col6")

for (i in cols_to_plot) {
  ggplot(data=d, aes_string(i, fill= 'col1')) + geom_density(alpha = 0.5)

} 

Comments

3

lapply() could be used here in place of a for loop with aes_string().

cols_to_plot <- c("col2","col4","col6")
lapply(cols_to_plot,function(i){
  ggplot(data=d, aes_string(x=i, fill= 'col1')) + 
    geom_density(alpha = 0.5)
} )

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.