1

Here is sample data where ID is a categorical variable.

ID <- c(12, 34, 560, 45, 235)
W1 <- c(0, 5, 7, 6, 0)
W2 <- c(7, 8, 9, 5, 2)
W3 <- c(0, 0, 3, 5, 9)
 
df <- data.frame(ID, W1, W2, W3)
df$ID <- as.factor(df$ID)

I want to draw five bar plots for each of these IDs using the frequency data for the three weeks W1:W3. In the actual dataset, I have 30+ weeks and around 150 IDs, hence the intention here is to do this efficiently. Nothing fancy, but ggplot would be ideal as I would need to manipulate some aesthetics.

How to do this using loop and save the images in one file(pdf)?

Thanks for your help!

1 Answer 1

2

This sort of problem is usually a data reformating problem. See reshaping data.frame from wide to long format. After reshaping the data, the plot is faceted by ID, avoiding loops.

library(ggplot2)

ID <- c(12, 34, 560, 45, 235)
W1 <- c(0, 5, 7, 6, 0)
W2 <- c(7, 8, 9, 5, 2)
W3 <- c(0, 0, 3, 5, 9)

df <- data.frame(ID, W1, W2, W3)
df$ID <- as.factor(df$ID)
df[-1] <- lapply(df[-1], as.integer)

df |>
  tidyr::pivot_longer(-ID, names_to = "Week", values_to = "Frequency") |>
  ggplot(aes(Week, Frequency, fill = Week)) +
  geom_col() +
  scale_y_continuous(breaks = scales::pretty_breaks()) +
  facet_wrap(~ ID) +
  theme_bw(base_size = 16)

Created on 2022-09-30 with reprex v2.0.2


Edit

If there is a mix of week numbers with 1 and 2 digits, the lexicographic order is not the numbers' order. For instance, after W1 comes W11, not W2. Package stringr function str_sort sorts by numbers when argument numeric = TRUE.
In the example below I reuse the data changing W2 to W11. The correct bars order should therefore be W1, W3, W11.

library(ggplot2)
library(stringr)

ID <- c(12, 34, 560, 45, 235)
W1 <- c(0, 5, 7, 6, 0)
W11 <- c(7, 8, 9, 5, 2)
W3 <- c(0, 0, 3, 5, 9)

df <- data.frame(ID, W1, W11, W3)
df$ID <- as.factor(df$ID)
df[-1] <- lapply(df[-1], as.integer)

df |>
  tidyr::pivot_longer(-ID, names_to = "Week", values_to = "Frequency") |>
  dplyr::mutate(Week = factor(Week, levels = str_sort(unique(Week), numeric = TRUE))) |>
  ggplot(aes(Week, Frequency, fill = Week)) +
  geom_col() +
  scale_y_continuous(breaks = scales::pretty_breaks()) +
  facet_wrap(~ ID) +
  theme_bw(base_size = 16)

Created on 2022-10-01 with reprex v2.0.2

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks! This worked perfectly until I ran into a weird problem. I can't seem to manage how to put the weeks in order. For example, following your method, I get a nice bargraph, but the weeks are ordered as w1, w11:19, w2, w21:29, w3, w31:35, whereas the columns in the data are ordered in ascending order (w1:w35). Any lead on how to change this to the right order that follows the order of columns in the data?
@Tathagato Use package stringr, function str_sort with argument numeric=TRUE to put the unique values in order then coerce to factor with those values as factors. I will post code later on today
@Tathagato Done, see the edit.

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.