Graphing With R

Jan 19, 2013 16:28 · 885 words · 5 minutes read Charts javascript R Yottaa

I took a few days off for Christmas in San Antonio with my parents and my sister. While there, I had the usual tasks for a geek with non-geek relatives: fix computers, fix wifi, fix printers, explain the Internet, explain how stuff works. But in between time spent doing that, and doing family stuff, I learned a bit about R. R is programming language mostly intended to do statistical programming. I don’t know much about that, but I wanted a way to make some graphs that are sometimes difficult to make in Excel.

I think it would be easier to just learn more about Excel, but now I am invested so I am trying to use it as much as possible. Recently at work I added a post to our blog on the impact of JavaScript and concatenating/minifying the code on your website. You can read the about it here At the end of that post, I added an chart describing the final results.

JavaScript tests chart built with R

JavaScript tests chart built with R

Creating a chart like this would probably take me 20-30 minutes in Excel. Building it in R would probably take less time if I knew R like I know Excel. Instead it took me a lot longer. But in getting there I discovered a lot of ways I didn’t like the image. I think Excel is great when you know exactly how you want the final image to appear in the post. I thought I did, but this looks vastly different from that initial version. Tweaking and then having a very repeatable chart within seconds for any dataset is one of R‘s biggest strengths for me.

So how did I get here? Well, R is complicated. Luckily a course on Coursera came up at exactly the right time for me. There is a second course that takes this further that starts next week too.

But assuming that you know the basics of R and just want to see what I did, here is my R Script for this chart (the csv files I am using are the standard ones you can download after running a test on Yottaa):

body, td {

font-family: sans-serif;

background-color: white;

font-size: 12px;

margin: 8px;

}

tt, code, pre {

font-family: ‘DejaVu Sans Mono’, ‘Droid Sans Mono’, ‘Lucida Console’, Consolas, Monaco, monospace;

}

h1 {

font-size:2.2em;

}

h2 {

font-size:1.8em;

}

h3 {

font-size:1.4em;

}

h4 {

font-size:1.0em;

}

h5 {

font-size:0.9em;

}

h6 {

font-size:0.8em;

}

a:visited {

color: rgb(50%, 0%, 50%);

}

pre {

margin-top: 0;

max-width: 95%;

border: 1px solid #ccc;

white-space: pre-wrap;

}

pre code {

display: block; padding: 0.5em;

}

code.r, code.cpp {

background-color: #F8F8F8;

}

table, td, th {

border: none;

}

blockquote {

color:#666666;

margin:0;

padding-left: 1em;

border-left: 0.5em #EEE solid;

}

hr {

height: 0px;

border-bottom: none;

border-top-width: thin;

border-top-style: dotted;

border-top-color: #999999;

}

@media print {

  • {

background: transparent !important;

color: black !important;

filter:none !important;

-ms-filter: none !important;

}

body {

font-size:12pt;

max-width:100%;

}

a, a:visited {

text-decoration: underline;

}

hr {

visibility: hidden;

page-break-before: always;

}

pre, blockquote {

padding-right: 1em;

page-break-inside: avoid;

}

tr, img {

page-break-inside: avoid;

}

img {

max-width: 100% !important;

}

@page :left {

margin: 15mm 20mm 15mm 10mm;

}

@page :right {

margin: 15mm 10mm 15mm 20mm;

}

p, h2, h3 {

orphans: 3; widows: 3;

}

h2, h3 {

page-break-after: avoid;

}

}

pre .operator,

pre .paren {

color: rgb(104, 118, 135)

}

pre .literal {

color: rgb(88, 72, 246)

}

pre .number {

color: rgb(0, 0, 205);

}

pre .comment {

color: rgb(76, 136, 107);

}

pre .keyword {

color: rgb(0, 0, 255);

}

pre .identifier {

color: rgb(0, 0, 0);

}

pre .string {

color: rgb(3, 106, 7);

}

var hljs=new function(){function m(p){return p.replace(/&/gm,”&”).replace(/‘+M[0]+”“}else{r+=M[0]}O=P.lR.lastIndex;M=P.lR.exec(L)}return r+L.substr(O,L.length-O)}function J(L,M){if(M.sL&&e[M.sL]){var r=d(M.sL,L);x+=r.keyword_count;return r.value}else{return F(L,M)}}function I(M,r){var L=M.cN?’‘:””;if(M.rB){y+=L;M.buffer=””}else{if(M.eB){y+=m®+L;M.buffer=””}else{y+=L;M.buffer=r}}D.push(M);A+=M.r}function G(N,M,Q){var R=D[D.length-1];if(Q){y+=J(R.buffer+N,R);return false}var P=q(M,R);if(P){y+=J(R.buffer+N,R);I(P,M);return P.rB}var L=v(D.length-1,M);if(L){var O=R.cN?”“:””;if(R.rE){y+=J(R.buffer+N,R)+O}else{if(R.eE){y+=J(R.buffer+N,R)+O+m(M)}else{y+=J(R.buffer+N+M,R)+O}}while(L>1){O=D[D.length-2].cN?”“:””;y+=O;L–;D.length–}var r=D[D.length-1];D.length–;D[D.length-1].buffer=””;if(r.starts){I(r.starts,””)}return R.rE}if(w(M,R)){throw”Illegal”}}var E=e[B];var D=[E.dM];var A=0;var x=0;var y=””;try{var s,u=0;E.dM.buffer=””;do{s=p(C,u);var t=G(s[0],s1,s2);u+=s[0].length;if(!t){u+=s1.length}}while(!s2);if(D.length>1){throw”Illegal”}return{r:A,keyword_count:x,value:y}}catch(H){if(H==”Illegal”){return{r:0,keyword_count:0,value:m©}}else{throw H}}}function g(t){var p={keyword_count:0,r:0,value:m(t)};var r=p;for(var q in e){if(!e.hasOwnProperty(q)){continue}var s=d(q,t);s.language=q;if(s.keyword_count+s.r>r.keyword_count+r.r){r=s}if(s.keyword_count+s.r>p.keyword_count+p.r){r=p;p=s}}if(r.language){p.second_best=r}return p}function i(r,q,p){if(q){r=r.replace(/^((]+>|t)+)/gm,function(t,w,v,u){return w.replace(/t/g,q)})}if(p){r=r.replace(/n/g,”
“)}return r}function n(t,w,r){var x=h(t,r);var v=a(t);var y,s;if(v){y=d(v,x)}else{return}var q=c(t);if(q.length){s=document.createElement(“pre”);s.innerHTML=y.value;y.value=k(q,c(s),x)}y.value=i(y.value,w,r);var u=t.className;if(!u.match(“(\s|^)(language-)?”+v+”(\s|$)”)){u=u?(u+” “+v):v}if(/MSIE [678]/.test(navigator.userAgent)&&t.tagName==”CODE”&&t.parentNode.tagName==”PRE”){s=t.parentNode;var p=document.createElement(“div”);p.innerHTML=”

"+y.value+"

“;t=p.firstChild.firstChild;p.firstChild.cN=s.cN;s.parentNode.replaceChild(p.firstChild,s)}else{t.innerHTML=y.value}t.className=u;t.result={language:v,kw:y.keyword_count,re:y.r};if(y.second_best){t.second_best={language:y.second_best.language,kw:y.second_best.keyword_count,re:y.second_best.r}}}function o(){if(o.called){return}o.called=true;var r=document.getElementsByTagName(“pre”);for(var p=0;p=|>>|>>=|>>>|>>>=|\?|[|{|(|\^|\^=||||=||||~”;this.ER=”(?![\s\S])”;this.BE={b:”\.”,r:0};this.ASM={cN:”string”,b:”‘”,e:”‘”,i:”\n”,c:[this.BE],r:0};this.QSM={cN:”string”,b:’”‘,e:’”‘,i:”\n”,c:[this.BE],r:0};this.CLCM={cN:”comment”,b:”//”,e:”$”};this.CBLCLM={cN:”comment”,b:”/*”,e:”*/”};this.HCM={cN:”comment”,b:”#”,e:”$”};this.NM={cN:”number”,b:this.NR,r:0};this.CNM={cN:”number”,b:this.CNR,r:0};this.BNM={cN:”number”,b:this.BNR,r:0};this.inherit=function(r,s){var p={};for(var q in r){p[q]=r[q]}if(s){for(var q in s){p[q]=s[q]}}return p}}();hljs.LANGUAGES.cpp=function(){var a={keyword:{“false”:1,”int”:1,”float”:1,”while”:1,”private”:1,”char”:1,”catch”:1,”export”:1,virtual:1,operator:2,sizeof:2,dynamic_cast:2,typedef:2,const_cast:2,”const”:1,struct:1,”for”:1,static_cast:2,union:1,namespace:1,unsigned:1,”long”:1,”throw”:1,”volatile”:2,”static”:1,”protected”:1,bool:1,template:1,mutable:1,”if”:1,”public”:1,friend:2,”do”:1,”return”:1,”goto”:1,auto:1,”void”:2,”enum”:1,”else”:1,”break”:1,”new”:1,extern:1,using:1,”true”:1,”class”:1,asm:1,”case”:1,typeid:1,”short”:1,reinterpret_cast:2,”default”:1,”double”:1,register:1,explicit:1,signed:1,typename:1,”try”:1,”this”:1,”switch”:1,”continue”:1,wchar_t:1,inline:1,”delete”:1,alignof:1,char16_t:1,char32_t:1,constexpr:1,decltype:1,noexcept:1,nullptr:1,static_assert:1,thread_local:1,restrict:1,_Bool:1,complex:1},built_in:{std:1,string:1,cin:1,cout:1,cerr:1,clog:1,stringstream:1,istringstream:1,ostringstream:1,auto_ptr:1,deque:1,list:1,queue:1,stack:1,vector:1,map:1,set:1,bitset:1,multiset:1,multimap:1,unordered_set:1,unordered_map:1,unordered_multiset:1,unordered_multimap:1,array:1,shared_ptr:1}};return{dM:{k:a,i:”</“,c:[hljs.CLCM,hljs.CBLCLM,hljs.QSM,{cN:“string”,b:“’\?.“,e:“‘”,i:“.”},{cN:“number”,b:”\b(\d+(.\d*)?|.\d+)(u|U|l|L|ul|UL|f|F)“},hljs.CNM,{cN:“preprocessor”,b:“#”,e:“$”},{cN:“stl_container”,b:”\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\s*”,k:a,r:10,c:[“self”]}]}}}();hljs.LANGUAGES.r={dM:{c:[hljs.HCM,{cN:”number”,b:”\b0[xX][0-9a-fA-F]+[Li]?\b”,e:hljs.IMMEDIATE_RE,r:0},{cN:”number”,b:”\b\d+(?:[eE][+-]?\d*)?L\b”,e:hljs.IMMEDIATE_RE,r:0},{cN:”number”,b:”\b\d+.(?!\d)(?:i\b)?”,e:hljs.IMMEDIATE_RE,r:1},{cN:”number”,b:”\b\d+(?:.\d*)?(?:[eE][+-]?\d*)?i?\b”,e:hljs.IMMEDIATE_RE,r:0},{cN:”number”,b:”.\d+(?:[eE][+-]?\d*)?i?\b”,e:hljs.IMMEDIATE_RE,r:1},{cN:”keyword”,b:”(?:tryCatch|library|setGeneric|setGroupGeneric)\b”,e:hljs.IMMEDIATE_RE,r:10},{cN:”keyword”,b:”...”,e:hljs.IMMEDIATE_RE,r:10},{cN:”keyword”,b:”..\d+(?![\w.])”,e:hljs.IMMEDIATE_RE,r:10},{cN:”keyword”,b:”\b(?:function)”,e:hljs.IMMEDIATE_RE,r:2},{cN:”keyword”,b:”(?:if|in|break|next|repeat|else|for|return|switch|while|try|stop|warning|require|attach|detach|source|setMethod|setClass)\b”,e:hljs.IMMEDIATE_RE,r:1},{cN:”literal”,b:”(?:NA|NA_integer_|NA_real_|NA_character_|NA_complex_)\b”,e:hljs.IMMEDIATE_RE,r:10},{cN:”literal”,b:”(?:NULL|TRUE|FALSE|T|F|Inf|NaN)\b”,e:hljs.IMMEDIATE_RE,r:1},{cN:”identifier”,b:”[a-zA-Z.][a-zA-Z0-9._]*\b”,e:hljs.IMMEDIATE_RE,r:0},{cN:”operator”,b:”|=||<|!|&|||\$|:“,e:hljs.IMMEDIATE_RE,r:0},{cN:“operator”,b:“%”,e:“%”,i:”\n”,r:1},{cN:“identifier”,b:”`”,e:”`”,r:0},{cN:“string”,b:‘“’,e:‘“’,c:[hljs.BE],r:0},{cN:“string”,b:“‘”,e:“‘”,c:[hljs.BE],r:0},{cN:“paren”,b:”[[({])}]“,e:hljs.IMMEDIATE_RE,r:0}]}};

hljs.initHighlightingOnLoad();

setwd("~/Downloads/")
library(ggplot2)
library(plyr)
js1 <- read.csv("Lat-JSTest-Jan14-Test1.csv")
js2 <- read.csv("Lat-JSTest-Jan14-Test2.csv")
js3 <- read.csv("Lat-JSTest-Jan14-Test3.csv")
js4 <- read.csv("Lat-JSTest-Jan14-Test4.csv")
js5 <- read.csv("Lat-JSTest-Jan14-Test5.csv")
alljs <- rbind(js1,js2,js3,js4,js5)
regions <- data.frame(Location=c("New York (NYC)", 
                                 "Chicago (ORD)",
                                 "Dallas (DFW)",
                                 "Washington DC (DCA)",
                                 "San Francisco (SFO)", 
                                 "Oregon (PDX)",
                                 "Amsterdam (AMS)",
                                 "Berlin (BER)",
                                 "Dublin (DUB)",
                                 "London (LDN)",
                                 "Tokyo (NRT)",
                                 "Hong Kong (HK)",
                                 "Sydney (SYD)"),
                      Region=c(rep("US",6),rep("Europe",4),rep("AsiaPac",3)))
alljsr <- merge(alljs,regions,by.x="Location")
mt <- ddply(alljsr,
            "Monitor.name", 
            summarise, 
            mt2i=median(time.to.interact),
            sd=sd(time.to.interact),
            se=sd(time.to.interact)/sqrt(length(time.to.interact))
            )

p <- ggplot(mt,aes(x=factor(Monitor.name),y=mt2i,fill=Monitor.name))
p.plot <- geom_bar(stat="identity")
p.error <- geom_errorbar(aes(ymin=mt2i-se,ymax=mt2i+se),width=0.10)
#p.error <- geom_errorbar(width=0.25)
p.coord <- coord_cartesian(ylim=c(1000,6000))
p.labs <- labs(color="black", title="Javascript Tests", y="Time to Interact", y="" )
p.theme <- theme(legend.position="none",
                 panel.grid.major=element_line(color="black",size=.3,linetype="dotted"),
                 #panel.grid.major.x=element_line(size=.6),
                 panel.grid.minor=element_line(color="black",size=.1,linetype="dotted"),
                 panel.grid.major.x=element_blank(),
                 panel.border=element_rect(color="black", fill=NA, size=.2),
                 panel.background=element_rect(fill="white")

)
p.sfill <- scale_x_discrete(name="Tests",
                               breaks=c("Lat-JSTest-Jan14-Test1",
                                        "Lat-JSTest-Jan14-Test2",
                                        "Lat-JSTest-Jan14-Test3",
                                        "Lat-JSTest-Jan14-Test4a",
                                        "Lat-JSTest-Jan14-Test5"),
                               labels=c("1) Initial Test",
                                        "2) Added JS",
                                        "3) Optimizednexcept JS",
                                        "4) Optimizednwith ReducenJavaScript Requests",
                                        "5) Optimizednwith ReducenJS Requestsn& JS Minify"))
p.text <- geom_text(size=8,aes(x=Monitor.name, y=mt2i-500, label=mt2i), color="white")


p + p.plot + p.labs + p.theme + p.coord + p.sfill+p.error +p.text 

I am having a lot of fun with R so far and I look forward to seeing what I come up with over the next few weeks. I have a series of posts coming up on the Yottaa Blog and plenty of opportunity to post more charts made with R.