Data Wrangling: Code Style

Day 09

Prof Amanda Luby

Carleton College
Stat 220 - Winter 2026

Which is easier to read?

group_by(colleges,region) %>% mutate(z_cost=(cost - mean(cost, na.rm=TRUE)) / sd(cost,na.rm = TRUE)) %>% ungroup() 
# A tibble: 187 × 14
   unitid school  type  city  state region admission_rate   act undergrads  cost
    <dbl> <chr>   <chr> <chr> <chr> <chr>           <dbl> <dbl>      <dbl> <dbl>
 1 228343 Southw… priv… Geor… TX    South…          0.490    26       1507 55886
 2 177719 Barnes… priv… Sain… MO    Plains         NA        NA        569    NA
 3 367884 Hodges… priv… Fort… FL    South…          0.612    NA        832 27425
 4 149781 Wheato… priv… Whea… IL    Great…          0.848    29       2358 49214
 5 135364 Luther… priv… Lith… GA    South…          0.5      NA        235    NA
 6 212601 Gannon… priv… Erie  PA    Mid E…          0.755    23       2866 44896
 7 133979 Florid… priv… Miam… FL    South…          0.400    NA       1049 27460
 8 117140 Univer… priv… La V… CA    Far W…          0.548    22       4516 58014
 9 152567 Trine … priv… Ango… IN    Great…          0.816    25       2120 46440
10 237057 Whitma… priv… Wall… WA    Far W…          0.559    31       1545 68082
# ℹ 177 more rows
# ℹ 4 more variables: grad_rate <dbl>, fy_retention <dbl>, fedloan <dbl>,
#   z_cost <dbl>
colleges %>%
  group_by(region) %>%
  mutate(z_cost = (cost - mean(cost, na.rm = TRUE)) / sd(cost, na.rm = TRUE)) %>%
  ungroup() 
# A tibble: 187 × 14
   unitid school  type  city  state region admission_rate   act undergrads  cost
    <dbl> <chr>   <chr> <chr> <chr> <chr>           <dbl> <dbl>      <dbl> <dbl>
 1 228343 Southw… priv… Geor… TX    South…          0.490    26       1507 55886
 2 177719 Barnes… priv… Sain… MO    Plains         NA        NA        569    NA
 3 367884 Hodges… priv… Fort… FL    South…          0.612    NA        832 27425
 4 149781 Wheato… priv… Whea… IL    Great…          0.848    29       2358 49214
 5 135364 Luther… priv… Lith… GA    South…          0.5      NA        235    NA
 6 212601 Gannon… priv… Erie  PA    Mid E…          0.755    23       2866 44896
 7 133979 Florid… priv… Miam… FL    South…          0.400    NA       1049 27460
 8 117140 Univer… priv… La V… CA    Far W…          0.548    22       4516 58014
 9 152567 Trine … priv… Ango… IN    Great…          0.816    25       2120 46440
10 237057 Whitma… priv… Wall… WA    Far W…          0.559    31       1545 68082
# ℹ 177 more rows
# ℹ 4 more variables: grad_rate <dbl>, fy_retention <dbl>, fedloan <dbl>,
#   z_cost <dbl>

Which is easier to read?

palmerpenguins::penguins |>
  filter(species == "Adelie") |>
  ggplot(aes(x = bill_length_mm, y = bill_depth_mm)) +
  geom_point() + 
  scale_color_viridis_d(option = "magma",end = .75) + 
  theme_bw(base_family = "Times") + 
  theme(legend.position = "none",
        panel.grid.minor = element_blank(),
        panel.grid.major.x = element_blank(),
        axis.title.x = element_text(color = "darkred"))
palmerpenguins::penguins |> filter(species=="Adelie") |> ggplot(aes(x =bill_length_mm, y= bill_depth_mm)) + geom_point() + scale_color_viridis_d(option = "magma",end = .75) + 
  theme_bw(base_family = "Times") + 
  theme(legend.position = "none", panel.grid.minor=element_blank(), panel.grid.major.x = element_blank(),
        axis.title.x = element_text(color="darkred"))

https://style.tidyverse.org

Example: Pipes and whitespace

|> should always have a space before it, and should usually be followed by a new line. After the first step, each line should be indented by two spaces.

Good:

iris |>
  summarize(across(where(is.numeric), mean), .by = Species) |>
  pivot_longer(!Species, names_to = "measure", values_to = "value") |>
  arrange(value)

Bad:

iris|> summarize(across(where(is.numeric), mean), .by = Species) |>
pivot_longer(!Species, names_to = "measure", values_to = "value")|>
arrange(value)

Example: long lines

If the arguments to a function don’t all fit on one line, put each argument on its own line and indent:

Good:

iris |>
  summarise(
    Sepal.Length = mean(Sepal.Length, na.rm = TRUE),
    Sepal.Width = mean(Sepal.Width, na.rm = TRUE),
    .by = Species
  )

Bad:

iris |>
  summarise(Sepal.Length = mean(Sepal.Length, na.rm = TRUE), Sepal.Width = mean(Sepal.Width, na.rm = TRUE), .by = Species)

ggplot2 whitespace and indenting

+ should always have a space before it, and should be followed by a new line. After the first step, each line should be indented by two spaces.

If you are creating a ggplot off of a dplyr pipeline, there should only be one level of indentation.

Good:

iris |>
  filter(Species == "setosa") |>
  ggplot(aes(x = Sepal.Width, y = Sepal.Length)) +
  geom_point()

Bad:

iris |>
  filter(Species == "setosa") |>
  ggplot(aes(x = Sepal.Width, y = Sepal.Length)) +
    geom_point()

Bad:

iris |>
  filter(Species == "setosa") |>
  ggplot(aes(x = Sepal.Width, y = Sepal.Length)) + geom_point()

ggplot2 long lines

If the arguments to a ggplot2 layer don’t all fit on one line, put each argument on its own line and indent:

Good:

iris |>
  ggplot(aes(x = Sepal.Width, y = Sepal.Length, color = Species)) +
  geom_point() +
  labs(
    x = "Sepal width, in cm",
    y = "Sepal length, in cm",
    title = "Sepal length vs. width of irises"
  )

Bad:

iris |>
  ggplot(aes(x = Sepal.Width, y = Sepal.Length, color = Species)) +
  geom_point() +
  labs(x = "Sepal width, in cm", y = "Sepal length, in cm", title = "Sepal length vs. width of irises")

Code style summary

  • All code style guides are opinionated and subjective
  • Using consistent style makes it easier for collaborators (including future you!) to read and understand your code
  • Try to follow the tidyverse style guide in this class

A shortcut

In RStudio,

  1. Highlight the code that you want to reformat
  2. Go to “code –> reformat code”
  3. Marvel in wonder

Try it

Reformat your code from an activity this week according to the tidyverse style guide