2

I know this question is really basic, but I am a total beginner and I have been the whole day trying to plot individual graphs for every single column of a data frame. Any help would be very useful

Here is the data:

> dfslices
        X0035.A061 X0094.B116 X0314.A038
verylow   19.48052   8.127208 36.8243243
low        2.96846   9.069494  7.4324324
medium     0.00000   2.237927  0.3378378
high       0.00000   0.000000  1.6891892

Basically, I need 1 barplot for each column (X0035.A061, X0094.B116 and X0314.A038). Each barplot has 4 bars (one bar correponding to the very low category, another to the low, another to the medium and another to the high). And it would be great the title of the graphs are (X0035.A061, X0094.B116 and X0314.A038) and every bar of the plot have the corresponding label (verylow, low, medium, and high)

Thank you

markus
  • 25,843
  • 5
  • 39
  • 58
misty28
  • 55
  • 1
  • 5
  • 4
    What have you tried so far? – Wolf Oct 15 '18 at 19:00
  • Could you make your problem reproducible by sharing a sample of your data and the code you're working on so others can help (please do not use `str()`, `head()` or screenshot)? You can use the [`reprex`](https://reprex.tidyverse.org/articles/articles/magic-reprex.html) and [`datapasta`](https://cran.r-project.org/web/packages/datapasta/vignettes/how-to-datapasta.html) packages to assist you with that. See also [Help me Help you](https://speakerdeck.com/jennybc/reprex-help-me-help-you?slide=5) & [How to make a great R reproducible example?](https://stackoverflow.com/q/5963269) – Tung Oct 15 '18 at 19:12

2 Answers2

7

Here is one solution to the problem using the data.table package for the melt() and fread() functions, and using facet_grid() from ggplot2 to plot all 3 of your original columns as separate panels on a single plot.

library(data.table)
library(ggplot2)

# Convert text data to data.table using fread() from the data.table package.
dfslice = fread("category X0035.A061 X0094.B116 X0314.A038
                 verylow    19.48052   8.127208 36.8243243
                 low         2.96846   9.069494  7.4324324
                 medium      0.00000   2.237927  0.3378378
                 high        0.00000   0.000000  1.6891892")

# Convert data to 'long form' using melt() from the data.table package.
mtab = melt(dfslice, id.vars="category")

# Manually set factor levels of 'category' column to plot in a logical order.
mtab$category = factor(mtab$category, 
                       levels=c("verylow", "low", "medium", "high"))

mtab
#     category   variable      value
#  1:  verylow X0035.A061 19.4805200
#  2:      low X0035.A061  2.9684600
#  3:   medium X0035.A061  0.0000000
#  4:     high X0035.A061  0.0000000
#  5:  verylow X0094.B116  8.1272080
#  6:      low X0094.B116  9.0694940
#  7:   medium X0094.B116  2.2379270
#  8:     high X0094.B116  0.0000000
#  9:  verylow X0314.A038 36.8243243
# 10:      low X0314.A038  7.4324324
# 11:   medium X0314.A038  0.3378378
# 12:     high X0314.A038  1.6891892

p = ggplot(data=mtab, aes(x=category, y=value, fill=category)) +
    geom_bar(stat="identity") +
    scale_fill_viridis_d() +
    facet_grid(. ~ variable)

ggsave("faceted_barplot.png", plot=p, width=7.5, height=2.5, dpi=150)

enter image description here

bdemarest
  • 14,397
  • 3
  • 53
  • 56
  • I wish I could upvote this again, I've spent the better part of an hour looking for a method to do exactly this! Thanks! – Ted May 07 '21 at 18:09
3

Here is one option

library(purrr)
library(tibble) # rownames_to_column
library(ggplot2)
plots <- split.default(dfslices, names(dfslices)) %>% 
  map(., setNames, nm = "col") %>% 
  map(., rownames_to_column) %>%
  map(., mutate, rowname = factor(rowname, levels = c("verylow", "low", "medium", "high"))) %>% 
  imap(., ~ {
    ggplot(.x, aes(rowname, col)) + 
      geom_col() +
      labs(title = .y)
    })

plots$X0035.A061

enter image description here

The idea is to create a list of dataframes, each containing a single column of dfslices. We use split.default to create that list.

In the next two lines we rename the columns in each dataframe to be "col" and for each dataframe convert its rownames to an explicit column. Next step, convert column rowname to factor and set its levels accordingly.

Finally can use imap to iterate of the list and over the names of that list which are symbolized by .y. We use .y as an argument to labs to have the title of each plot correspond to the (former) column name.

data

dfslices <- structure(list(X0035.A061 = c(19.48052, 2.96846, 0, 0), X0094.B116 = c(8.127208, 
9.069494, 2.237927, 0), X0314.A038 = c(36.8243243, 7.4324324, 
0.3378378, 1.6891892)), .Names = c("X0035.A061", "X0094.B116", 
"X0314.A038"), class = "data.frame", row.names = c("verylow", 
"low", "medium", "high"))
markus
  • 25,843
  • 5
  • 39
  • 58
  • 1
    Downvoters, please consider also providing some suggestions that would, in your view, improve the answer. – bdemarest Oct 16 '18 at 05:07