library(reshape2)
package ‘reshape2’ was built under R version 3.3.2
library(ggplot2)
package ‘ggplot2’ was built under R version 3.3.2
library(dplyr)
package ‘dplyr’ was built under R version 3.3.2
Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
library(broom)
data <- read.csv("csv/all.csv")
data$date <- as.Date(data$date)
cutoff_date = "2016-10-15"

Filtering and plotting

Then we define a function that can be used to filter the dataset to a particular encounter and difficulty. It also performs outlier filtering - for each 5-ilvl bucket, for each spec, we compute the 95th percentile of DPS, then remove any parses from the dataset for that ilvl/spec above that cutoff.

d <- data
m <- d %>% group_by(class, spec, encounter, difficulty) %>% do(tidy(lm(dps ~ ilvl, data=.)))
slopes <- m[m$term == "ilvl",]
slopes <- m[m$term == "ilvl",]
d <- data
m <- d %>% group_by(class, spec) %>% do(tidy(lm(dps ~ ilvl, data=.)))

|=====================================================================================                                                                                     | 50% ~2 s remaining     
|============================================================================================                                                                              | 54% ~2 s remaining     
|===================================================================================================                                                                       | 58% ~2 s remaining     
|==========================================================================================================                                                                | 62% ~2 s remaining     
|=================================================================================================================                                                         | 67% ~2 s remaining     
|========================================================================================================================                                                  | 71% ~1 s remaining     
|===============================================================================================================================                                           | 75% ~1 s remaining     
|======================================================================================================================================                                    | 79% ~1 s remaining     
|=============================================================================================================================================                             | 83% ~1 s remaining     
|====================================================================================================================================================                      | 88% ~1 s remaining     
|===========================================================================================================================================================               | 92% ~0 s remaining     
|==================================================================================================================================================================        | 96% ~0 s remaining     
|==========================================================================================================================================================================|100% ~0 s remaining     
all_slopes <- m[m$term == "ilvl",]
scale_encounter <- function(s, title) {
  s <- filter(s, estimate > 0)
  s$class = with(s, factor(class, levels = rev(levels(class))))
  s$spec = with(s, factor(spec, levels = rev(levels(spec))))
  ggplot(data=s, aes(x=paste(class, spec), y=estimate, group=interaction(class, spec), reorder=estimate, fill=paste(class,spec))) +
    geom_bar(position=position_dodge(width = 0.9), stat="identity") +
    labs(y="DPS gain/ilvl", x="Encounter", title=paste("DPS scaling per ilvl:", title)) +
    coord_flip() +
    guides(fill=FALSE)
}
scale_encounter(filter(slopes, encounter == "Nythendra", difficulty == "Normal"), title="Nythendra Normal")

scale_encounter(filter(slopes, encounter == "Nythendra", difficulty == "Heroic"), title="Nythendra Heroic")

scale_encounter(filter(slopes, encounter == "Nythendra", difficulty == "Mythic"), title="Nythendra Mythic")

scale_encounter(filter(slopes, encounter == "Ursoc", difficulty == "Normal"), title="Ursoc Normal")

scale_encounter(filter(slopes, encounter == "Ursoc", difficulty == "Heroic"), title="Ursoc Heroic")

scale_encounter(filter(slopes, encounter == "Ursoc", difficulty == "Mythic"), title="Ursoc Mythic")

scale_encounter(filter(slopes, encounter == "Dragons_of_Nightmare", difficulty == "Normal"), title="Dragons_of_Nightmare Normal")

scale_encounter(filter(slopes, encounter == "Dragons_of_Nightmare", difficulty == "Heroic"), title="Dragons_of_Nightmare Heroic")

scale_encounter(filter(slopes, encounter == "Dragons_of_Nightmare", difficulty == "Mythic"), title="Dragons_of_Nightmare Mythic")

scale_encounter(filter(slopes, encounter == "Elerethe_Renferal", difficulty == "Normal"), title="Elerethe_Renferal Normal")

scale_encounter(filter(slopes, encounter == "Elerethe_Renferal", difficulty == "Heroic"), title="Elerethe_Renferal Heroic")

scale_encounter(filter(slopes, encounter == "Elerethe_Renferal", difficulty == "Mythic"), title="Elerethe_Renferal Mythic")

scale_encounter(filter(slopes, encounter == "Il_gynoth__Heart_of_Corruption", difficulty == "Normal"), title="Il_gynoth__Heart_of_Corruption Normal")

scale_encounter(filter(slopes, encounter == "Il_gynoth__Heart_of_Corruption", difficulty == "Heroic"), title="Il_gynoth__Heart_of_Corruption Heroic")

scale_encounter(filter(slopes, encounter == "Il_gynoth__Heart_of_Corruption", difficulty == "Mythic"), title="Il_gynoth__Heart_of_Corruption Mythic")

scale_encounter(filter(slopes, encounter == "Cenarius", difficulty == "Normal"), title="Cenarius Normal")

scale_encounter(filter(slopes, encounter == "Cenarius", difficulty == "Heroic"), title="Cenarius Heroic")

scale_encounter(filter(slopes, encounter == "Cenarius", difficulty == "Mythic"), title="Cenarius Mythic")

scale_encounter(filter(slopes, encounter == "Xavius", difficulty == "Normal"), title="Xavius Normal")

scale_encounter(filter(slopes, encounter == "Xavius", difficulty == "Heroic"), title="Xavius Heroic")

scale_encounter(filter(slopes, encounter == "Xavius", difficulty == "Mythic"), title="Xavius Mythic")

scale_encounter(all_slopes, title="Overall")

LS0tDQp0aXRsZTogIkFsbCBzcGVjIHNjYWxpbmciDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IA0KICAgIGZpZ19oZWlnaHQ6IDYNCiAgICBmaWdfd2lkdGg6IDE4DQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KLS0tDQoNCmBgYHtyfQ0KbGlicmFyeShyZXNoYXBlMikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGJyb29tKQ0KZGF0YSA8LSByZWFkLmNzdigiY3N2L2FsbC5jc3YiKQ0KZGF0YSRkYXRlIDwtIGFzLkRhdGUoZGF0YSRkYXRlKQ0KY3V0b2ZmX2RhdGUgPSAiMjAxNi0xMC0xNSINCmBgYA0KDQojIyBGaWx0ZXJpbmcgYW5kIHBsb3R0aW5nDQoNClRoZW4gd2UgZGVmaW5lIGEgZnVuY3Rpb24gdGhhdCBjYW4gYmUgdXNlZCB0byBmaWx0ZXIgdGhlIGRhdGFzZXQgdG8gYSBwYXJ0aWN1bGFyIGVuY291bnRlciBhbmQgZGlmZmljdWx0eS4gSXQgYWxzbyBwZXJmb3JtcyBvdXRsaWVyIGZpbHRlcmluZyAtIGZvciBlYWNoIDUtaWx2bCBidWNrZXQsIGZvciBlYWNoIHNwZWMsIHdlIGNvbXB1dGUgdGhlIDk1dGggcGVyY2VudGlsZSBvZiBEUFMsIHRoZW4gcmVtb3ZlIGFueSBwYXJzZXMgZnJvbSB0aGUgZGF0YXNldCBmb3IgdGhhdCBpbHZsL3NwZWMgYWJvdmUgdGhhdCBjdXRvZmYuDQoNCmBgYHtyfQ0KZCA8LSBkYXRhDQptIDwtIGQgJT4lIGdyb3VwX2J5KGNsYXNzLCBzcGVjLCBlbmNvdW50ZXIsIGRpZmZpY3VsdHkpICU+JSBkbyh0aWR5KGxtKGRwcyB+IGlsdmwsIGRhdGE9LikpKQ0Kc2xvcGVzIDwtIG1bbSR0ZXJtID09ICJpbHZsIixdDQpgYGANCmBgYHtyfQ0KZCA8LSBkYXRhDQptIDwtIGQgJT4lIGdyb3VwX2J5KGNsYXNzLCBzcGVjKSAlPiUgZG8odGlkeShsbShkcHMgfiBpbHZsLCBkYXRhPS4pKSkNCmFsbF9zbG9wZXMgPC0gbVttJHRlcm0gPT0gImlsdmwiLF0NCmBgYA0KDQpgYGB7ciwgZmlnLndpZHRoPTcuNSwgZmlnLmhlaWdodD03fQ0Kc2NhbGVfZW5jb3VudGVyIDwtIGZ1bmN0aW9uKHMsIHRpdGxlKSB7DQogIHMgPC0gZmlsdGVyKHMsIGVzdGltYXRlID4gMCkNCiAgcyRjbGFzcyA9IHdpdGgocywgZmFjdG9yKGNsYXNzLCBsZXZlbHMgPSByZXYobGV2ZWxzKGNsYXNzKSkpKQ0KICBzJHNwZWMgPSB3aXRoKHMsIGZhY3RvcihzcGVjLCBsZXZlbHMgPSByZXYobGV2ZWxzKHNwZWMpKSkpDQogIGdncGxvdChkYXRhPXMsIGFlcyh4PXBhc3RlKGNsYXNzLCBzcGVjKSwgeT1lc3RpbWF0ZSwgZ3JvdXA9aW50ZXJhY3Rpb24oY2xhc3MsIHNwZWMpLCByZW9yZGVyPWVzdGltYXRlLCBmaWxsPXBhc3RlKGNsYXNzLHNwZWMpKSkgKw0KICAgIGdlb21fYmFyKHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC45KSwgc3RhdD0iaWRlbnRpdHkiKSArDQogICAgbGFicyh5PSJEUFMgZ2Fpbi9pbHZsIiwgeD0iRW5jb3VudGVyIiwgdGl0bGU9cGFzdGUoIkRQUyBzY2FsaW5nIHBlciBpbHZsOiIsIHRpdGxlKSkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgZ3VpZGVzKGZpbGw9RkFMU0UpDQp9DQpzY2FsZV9lbmNvdW50ZXIoZmlsdGVyKHNsb3BlcywgZW5jb3VudGVyID09ICJOeXRoZW5kcmEiLCBkaWZmaWN1bHR5ID09ICJOb3JtYWwiKSwgdGl0bGU9Ik55dGhlbmRyYSBOb3JtYWwiKQ0Kc2NhbGVfZW5jb3VudGVyKGZpbHRlcihzbG9wZXMsIGVuY291bnRlciA9PSAiTnl0aGVuZHJhIiwgZGlmZmljdWx0eSA9PSAiSGVyb2ljIiksIHRpdGxlPSJOeXRoZW5kcmEgSGVyb2ljIikNCnNjYWxlX2VuY291bnRlcihmaWx0ZXIoc2xvcGVzLCBlbmNvdW50ZXIgPT0gIk55dGhlbmRyYSIsIGRpZmZpY3VsdHkgPT0gIk15dGhpYyIpLCB0aXRsZT0iTnl0aGVuZHJhIE15dGhpYyIpDQoNCnNjYWxlX2VuY291bnRlcihmaWx0ZXIoc2xvcGVzLCBlbmNvdW50ZXIgPT0gIlVyc29jIiwgZGlmZmljdWx0eSA9PSAiTm9ybWFsIiksIHRpdGxlPSJVcnNvYyBOb3JtYWwiKQ0Kc2NhbGVfZW5jb3VudGVyKGZpbHRlcihzbG9wZXMsIGVuY291bnRlciA9PSAiVXJzb2MiLCBkaWZmaWN1bHR5ID09ICJIZXJvaWMiKSwgdGl0bGU9IlVyc29jIEhlcm9pYyIpDQpzY2FsZV9lbmNvdW50ZXIoZmlsdGVyKHNsb3BlcywgZW5jb3VudGVyID09ICJVcnNvYyIsIGRpZmZpY3VsdHkgPT0gIk15dGhpYyIpLCB0aXRsZT0iVXJzb2MgTXl0aGljIikNCg0Kc2NhbGVfZW5jb3VudGVyKGZpbHRlcihzbG9wZXMsIGVuY291bnRlciA9PSAiRHJhZ29uc19vZl9OaWdodG1hcmUiLCBkaWZmaWN1bHR5ID09ICJOb3JtYWwiKSwgdGl0bGU9IkRyYWdvbnNfb2ZfTmlnaHRtYXJlIE5vcm1hbCIpDQpzY2FsZV9lbmNvdW50ZXIoZmlsdGVyKHNsb3BlcywgZW5jb3VudGVyID09ICJEcmFnb25zX29mX05pZ2h0bWFyZSIsIGRpZmZpY3VsdHkgPT0gIkhlcm9pYyIpLCB0aXRsZT0iRHJhZ29uc19vZl9OaWdodG1hcmUgSGVyb2ljIikNCnNjYWxlX2VuY291bnRlcihmaWx0ZXIoc2xvcGVzLCBlbmNvdW50ZXIgPT0gIkRyYWdvbnNfb2ZfTmlnaHRtYXJlIiwgZGlmZmljdWx0eSA9PSAiTXl0aGljIiksIHRpdGxlPSJEcmFnb25zX29mX05pZ2h0bWFyZSBNeXRoaWMiKQ0KDQpzY2FsZV9lbmNvdW50ZXIoZmlsdGVyKHNsb3BlcywgZW5jb3VudGVyID09ICJFbGVyZXRoZV9SZW5mZXJhbCIsIGRpZmZpY3VsdHkgPT0gIk5vcm1hbCIpLCB0aXRsZT0iRWxlcmV0aGVfUmVuZmVyYWwgTm9ybWFsIikNCnNjYWxlX2VuY291bnRlcihmaWx0ZXIoc2xvcGVzLCBlbmNvdW50ZXIgPT0gIkVsZXJldGhlX1JlbmZlcmFsIiwgZGlmZmljdWx0eSA9PSAiSGVyb2ljIiksIHRpdGxlPSJFbGVyZXRoZV9SZW5mZXJhbCBIZXJvaWMiKQ0Kc2NhbGVfZW5jb3VudGVyKGZpbHRlcihzbG9wZXMsIGVuY291bnRlciA9PSAiRWxlcmV0aGVfUmVuZmVyYWwiLCBkaWZmaWN1bHR5ID09ICJNeXRoaWMiKSwgdGl0bGU9IkVsZXJldGhlX1JlbmZlcmFsIE15dGhpYyIpDQoNCnNjYWxlX2VuY291bnRlcihmaWx0ZXIoc2xvcGVzLCBlbmNvdW50ZXIgPT0gIklsX2d5bm90aF9fSGVhcnRfb2ZfQ29ycnVwdGlvbiIsIGRpZmZpY3VsdHkgPT0gIk5vcm1hbCIpLCB0aXRsZT0iSWxfZ3lub3RoX19IZWFydF9vZl9Db3JydXB0aW9uIE5vcm1hbCIpDQpzY2FsZV9lbmNvdW50ZXIoZmlsdGVyKHNsb3BlcywgZW5jb3VudGVyID09ICJJbF9neW5vdGhfX0hlYXJ0X29mX0NvcnJ1cHRpb24iLCBkaWZmaWN1bHR5ID09ICJIZXJvaWMiKSwgdGl0bGU9IklsX2d5bm90aF9fSGVhcnRfb2ZfQ29ycnVwdGlvbiBIZXJvaWMiKQ0Kc2NhbGVfZW5jb3VudGVyKGZpbHRlcihzbG9wZXMsIGVuY291bnRlciA9PSAiSWxfZ3lub3RoX19IZWFydF9vZl9Db3JydXB0aW9uIiwgZGlmZmljdWx0eSA9PSAiTXl0aGljIiksIHRpdGxlPSJJbF9neW5vdGhfX0hlYXJ0X29mX0NvcnJ1cHRpb24gTXl0aGljIikNCg0Kc2NhbGVfZW5jb3VudGVyKGZpbHRlcihzbG9wZXMsIGVuY291bnRlciA9PSAiQ2VuYXJpdXMiLCBkaWZmaWN1bHR5ID09ICJOb3JtYWwiKSwgdGl0bGU9IkNlbmFyaXVzIE5vcm1hbCIpDQpzY2FsZV9lbmNvdW50ZXIoZmlsdGVyKHNsb3BlcywgZW5jb3VudGVyID09ICJDZW5hcml1cyIsIGRpZmZpY3VsdHkgPT0gIkhlcm9pYyIpLCB0aXRsZT0iQ2VuYXJpdXMgSGVyb2ljIikNCnNjYWxlX2VuY291bnRlcihmaWx0ZXIoc2xvcGVzLCBlbmNvdW50ZXIgPT0gIkNlbmFyaXVzIiwgZGlmZmljdWx0eSA9PSAiTXl0aGljIiksIHRpdGxlPSJDZW5hcml1cyBNeXRoaWMiKQ0KDQpzY2FsZV9lbmNvdW50ZXIoZmlsdGVyKHNsb3BlcywgZW5jb3VudGVyID09ICJYYXZpdXMiLCBkaWZmaWN1bHR5ID09ICJOb3JtYWwiKSwgdGl0bGU9Ilhhdml1cyBOb3JtYWwiKQ0Kc2NhbGVfZW5jb3VudGVyKGZpbHRlcihzbG9wZXMsIGVuY291bnRlciA9PSAiWGF2aXVzIiwgZGlmZmljdWx0eSA9PSAiSGVyb2ljIiksIHRpdGxlPSJYYXZpdXMgSGVyb2ljIikNCnNjYWxlX2VuY291bnRlcihmaWx0ZXIoc2xvcGVzLCBlbmNvdW50ZXIgPT0gIlhhdml1cyIsIGRpZmZpY3VsdHkgPT0gIk15dGhpYyIpLCB0aXRsZT0iWGF2aXVzIE15dGhpYyIpDQoNCnNjYWxlX2VuY291bnRlcihhbGxfc2xvcGVzLCB0aXRsZT0iT3ZlcmFsbCIpDQpgYGA=