Alternative ggplot2 use: Crochet Patterns

Data Art ggplot2

Making crochet pattern design decisions with ggplot2

Ryan McShane https://ryanmcshane.com , Amy Nussbaum https://datascience.uchicago.edu/people/amy-nussbaum
2024-06-12

Just a lazy Monday afternoon

Sometimes, you and your significant other are attending a virtual statistics conference (eCOTS) and she decides to continue crocheting a Chicago flag-inspired baby blanket for her cousin’s baby shower (Ravelry “field of daisies” pattern linked here). Clearly, this is a common occurrence.

Chicago flag

Figure 1: Chicago flag

She’s made 27 granny squares, all with a red circle. She wants to make a six square by nine square blanket, so needs 54 squares and isn’t confident on how to proceed, design-wise. Here are two exemplar squares:

And overall progress at this point:

You think that 54 red dots (every square) might not look that good, but are having a hard time making your case. Obviously, you need to create a ggplot2 so that she can compare the two pattern ideas!

The Mission

First, you need to find the colors of the Chicago flag:

lblue = "#B3DDF2"
white = "#FFFFFF"
red = "#FF0000"
scales::show_col(c(lblue, white, red), ncol = 3)

Then, create a tibble (extension of data.frame) with the data needed to make the plot. inner* is the color of the center circle in the granny square, mid and outer are alternating colors, and x and y are the locations at which to plot the squares.

flag_colors = tibble(
  inner1 = rep(red, 54), 
  mid = rep(c(lblue, white), 27),
  outer = rep(c(white, lblue), 27), 
  x = rep(1:6, each = 9), 
  y = rep(1:9, times = 6),
# 2 - 4 not shown
  inner2 = rep(c(red, lblue, white, red), times = 14)[1:54], 
  inner3 = rep(c(white, red, red, lblue), times = 14)[1:54], 
  picker4 = sample(rep(c(1, 2), times = 27)),
  inner4 = if_else(picker4 == 1, outer, red), 
# I learned mapping was "up and down"
# "cleverly" used matrix byrow parameter to swap to "left to right"
  picker5 = rep(c(red, red, "a", "a"), times = 14)[1:54] |>
    matrix(nrow = 9, ncol = 6, byrow = TRUE) |>
    as.vector(),
  inner5 = if_else(picker5 == "a", outer, red)
)

Then, you write a function to plot any established inner* pattern. With a little help from Wolfram’s page on Regular Pentagons (equations 5 - 8), you are able to create a relatively high fidelity “daisy” shape.

patch_plot = function(data, inner, cons = 2.15, radius = 0.25){
  c1 = 0.25*(sqrt(5) - 1)*radius
  c2 = 0.25*(sqrt(5) + 1)*radius
  s1 = 0.25*(sqrt(10 + 2*sqrt(5)))*radius
  s2 = 0.25*(sqrt(10 - 2*sqrt(5)))*radius

  ggplot(data = {{data}}, aes(x = x, y = y, color = mid)) +
    geom_point(aes(color = outer), size = 16*cons, shape = 15) +
    geom_point(aes(y = y + radius), size = 5*cons) +
    geom_point(aes(x = x + s1, y = y + c1), size = 5*cons) +
    geom_point(aes(x = x + s2, y = y - c2), size = 5*cons) +
    geom_point(aes(x = x - s2, y = y - c2), size = 5*cons) +
    geom_point(aes(x = x - s1, y = y + c1), size = 5*cons) +
    geom_point(aes(color = {{inner}}), size = 4*cons) + 
    scale_color_identity() + 
    coord_fixed() + 
    xlim(c(0.5, 6.5)) +
    ylim(c(0.5, 9.5)) +
    theme_void()
}

Finally, you want to compare two options – one with all red dots, and one with about half red dots.

amy = patch_plot(data = flag_colors, inner = inner1)
ryan = patch_plot(data = flag_colors, inner = inner5)

ggsave(filename = "amy.png", plot = amy, width = 7, height = 10)
ggsave(filename = "ryan.png", plot = ryan, width = 7, height = 10)

knitr::include_graphics("amy.png")
Amy's preferred pattern

Figure 2: Amy’s preferred pattern

knitr::include_graphics("ryan.png")
Ryan's preferred pattern

Figure 3: Ryan’s preferred pattern

Conclusion

Alas, your significant other was not convinced. BUT you had fun making a ggplot function in the process, she was impressed with your ability to represent the design with ggplot, and she was more confident in her decision to complete the pattern as planned.