suppressPackageStartupMessages(library(gdata))
suppressPackageStartupMessages(library(dplyr))
suppressPackageStartupMessages(library(tidyr))
suppressPackageStartupMessages(library(htmlwidgets))
suppressPackageStartupMessages(library(metricsgraphics))
suppressPackageStartupMessages(library(RColorBrewer))
dat <- read.xls("~/data/BulletinSearch.xlsx")
bulletin_summary <- dat %>%
  mutate(Date.Posted=as.Date(as.character(Date.Posted)),
         Severity=as.character(Severity)) %>%
  select(Date.Posted, Bulletin.ID, Severity, Affected.Product) %>%
  group_by(Date.Posted, Bulletin.ID, Severity) %>%
  summarise(prod_count=n()) %>%
  group_by(Date.Posted, Severity) %>%
  mutate(bulletin_count=n(), prod_count_total=sum(prod_count)) %>%
  group_by(Date.Posted, Severity) %>%
  mutate(avg_prods_per_bulletin=round(prod_count_total/bulletin_count)) %>%
  distinct(Date.Posted, Severity) %>% ungroup() %>%
  arrange(desc(Date.Posted), desc(Bulletin.ID)) %>%
  select(-Bulletin.ID, -prod_count) %>%
  merge(expand(., Date.Posted, Severity), all.y=TRUE) %>%
  mutate(bulletin_count=ifelse(is.na(bulletin_count), 0, bulletin_count),
         avg_prods_per_bulletin=ifelse(is.na(avg_prods_per_bulletin), 0, avg_prods_per_bulletin)) %>%
  arrange(Date.Posted) %>%
  filter(!(Severity %in% c("None")), bulletin_count>0) %>%
  mjs_plot(x=Date.Posted, y=bulletin_count) %>%
  mjs_point(point_size=3, size_range=c(3, 10),
            color_accessor=Severity,
            color_type="category",
            color_range=brewer.pal(n=5, name="Set2"),
            size_accessor=avg_prods_per_bulletin) %>%
  mjs_axis_x(xax_format="date") %>%
  mjs_labs(y="# Bulletins")

Microsoft Security Bulletin history by severity & avg products count/bulletin