<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/ggplot-doodling-with-hibp-breaches/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://rud.is/b/2018/07/29/ggplot-doodling-with-hibp-breaches/"> R – rud.is</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>After reading <a rel="nofollow" href="https://github.com/themains/pwned" target="_blank">this interesting analysis</a> of <em>“How Often Are Americans’ Accounts Breached?”</em> by <a rel="nofollow" href="http://www.gsood.com/" target="_blank">Gaurav Sood</a> (which we need more of in cyber-land) I gave in to the impulse to do some gg-doodling with the “Have I Been Pwnd” JSON data he used.</p>
<p>It’s just some basic data manipulation with some heavy ggplot2 styling customization, so no real need for exposition beyond noting that there are many other ways to view the data. I just settled on centered segments early on and went from there. If you do a bit of gg-doodling yourself, drop a note in the comments with a link.</p>
<p>You can see a full-size version of the image via <a rel="nofollow" href="https://rud.is/b/wp-content/uploads/2018/07/hibp-lines.png" target="_blank">this link</a>.</p>
<pre><code>library(hrbrthemes) # use github or gitlab version
library(tidyverse)

# get the data

dat_url &lt;- &quot;https://raw.githubusercontent.com/themains/pwned/master/data/breaches.json&quot;

jsonlite::fromJSON(dat_url) %>% 
  mutate(BreachDate = as.Date(BreachDate)) %>% 
  tbl_df() -> breaches

# selected breach labels df
group_by(breaches, year = lubridate::year(BreachDate)) %>% 
  top_n(1, wt=PwnCount) %>% 
  ungroup() %>% 
  filter(year %in% c(2008, 2015, 2016, 2017)) %>% # pick years where labels will fit nicely
  mutate(
    lab = sprintf(&quot;%s\n%sM accounts&quot;, Name, as.integer(PwnCount/1000000))
  ) %>% 
  arrange(year) -> labs

# num of known breaches in that year for labels
count(breaches, year = lubridate::year(BreachDate)) %>% 
  mutate(nlab = sprintf(&quot;n=%s&quot;, n)) %>% 
  mutate(lab_x = as.Date(sprintf(&quot;%s-07-02&quot;, year))) -> year_cts

mutate(breaches, p_half = PwnCount/2) %>% # for centered segments
  ggplot() +
  geom_segment( # centered segments
    aes(BreachDate, p_half, xend=BreachDate, yend=-p_half), 
    color = ft_cols$yellow, size = 0.3
  ) +
  geom_text( # selected breach labels
    data = labs, aes(BreachDate, PwnCount/2, label = lab),
    lineheight = 0.875, size = 3.25, family = font_rc,
    hjust = c(0, 1, 1, 0), vjust = 1, nudge_x = c(25, -25, -25, 25),
    nudge_y = 0,  color = ft_cols$slate
  ) +
  geom_text( # top year labels
    data = year_cts, aes(lab_x, Inf, label = year), family = font_rc, 
    size = 4, vjust = 1, lineheight = 0.875, color = ft_cols$gray
  ) +
  geom_text( # bottom known breach count totals
    data = year_cts, aes(lab_x, -Inf, label = nlab, size = n), 
    vjust = 0, lineheight = 0.875, color = ft_cols$peach,
    family = font_rc, show.legend = FALSE
  ) +
  scale_x_date( # break on year
    name = NULL, date_breaks = &quot;1 year&quot;, date_labels = &quot;%Y&quot;
  ) +
  scale_y_comma(name = NULL, limits = c(-450000000, 450000000)) + # make room for labels
  scale_size_continuous(range = c(3, 4.5)) + # tolerable font sizes 
  labs(
    title = &quot;HIBP (Known) Breach Frequency &amp; Size&quot;,
    subtitle = &quot;Segment length is number of accounts; n=# known account breaches that year&quot;,
    caption = &quot;Source: HIBP via </code></pre>