block by timelyportfolio 3145541

axys to excel to d3 to r and back

Full Screen

index.html

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8" />
  <title>d3.js Axys Chart</title>
  <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
  Remove this if you use the .htaccess -->
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />

  <script  src="//d3js.org/d3.v2.min.js?2.9.1"></script>         <style>
            .axis path, .axis line {
                fill: none;
                stroke: #000;
                shape-rendering: crispEdges;
            }
     
            .labels, .barlabels {
                font: 0.7em arial;
            }
        </style>
</head><body><h3>d3.js Axys Chart    <a href="//ramblings.mcpher.com">(thanks so much to ramblings.mcpher.com)</a></h3>
    <table><tr>
        <td id="statustd">
            <div id="wsdi_status"> Connection not initialized </div>
        </td>
    </table>
    <input type=button id="send" value="Send to R" onclick="sendtoR();"/>
    <br>    <script>
            var perfdata = new Array();

            var margin = {top: 20, right: 60, bottom: 60, left: 60},
                width = 1000 - margin.right - margin.left,
                height = 500 - margin.top - margin.bottom;
            
            var x = d3.time.scale()
                .range([0, width - 60]);
            
            var y = d3.scale.linear()
                .range([height - 20, 0]);
            
            var duration = 1500,
                delay = 500;
            
            var color = d3.scale.category10();
            
            var svg = d3.select("body").append("svg")
                .attr("id","svgchart")
                .attr("width", width + margin.right + margin.left)
                .attr("height", height + margin.top + margin.bottom)
                .append("g")
                    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
            
            var parse = d3.time.format("%m/%d/%Y").parse, format = d3.time.format("%Y"),
              perfdata = new Array();   
         </script><script> var data, origdata = {
   "cDataSet":[      {
         "date":"12/31/1991",
         "portfolio":"16.27",
         "sp500":"30.47"
      },
      {
         "date":"12/31/1992",
         "portfolio":"7.99",
         "sp500":"7.62"
      },
      {
         "date":"12/31/1993",
         "portfolio":"6.55",
         "sp500":"10.08"
      },
      {
         "date":"12/31/1994",
         "portfolio":"0.44",
         "sp500":"1.32"
      },
      {
         "date":"12/31/1995",
         "portfolio":"16.08",
         "sp500":"37.58"
      },
      {
         "date":"12/31/1996",
         "portfolio":"11.56",
         "sp500":"22.96"
      },
      {
         "date":"12/31/1997",
         "portfolio":"18.2",
         "sp500":"33.36"
      },
      {
         "date":"12/31/1998",
         "portfolio":"13.98",
         "sp500":"28.58"
      },
      {
         "date":"12/31/1999",
         "portfolio":"9.09",
         "sp500":"21.04"
      },
      {
         "date":"12/31/2000",
         "portfolio":"0.13",
         "sp500":"-9.1"
      },
      {
         "date":"12/31/2001",
         "portfolio":"-4.83",
         "sp500":"-11.89"
      },
      {
         "date":"12/31/2002",
         "portfolio":"-7.81",
         "sp500":"-22.1"
      },
      {
         "date":"12/31/2003",
         "portfolio":"16.2",
         "sp500":"28.68"
      },
      {
         "date":"12/31/2004",
         "portfolio":"7.97",
         "sp500":"10.88"
      },
      {
         "date":"12/31/2005",
         "portfolio":"5.57",
         "sp500":"4.91"
      },
      {
         "date":"12/31/2006",
         "portfolio":"11.69",
         "sp500":"15.79"
      },
      {
         "date":"12/31/2007",
         "portfolio":"6.92",
         "sp500":"5.49"
      },
      {
         "date":"12/31/2008",
         "portfolio":"-25",
         "sp500":"-37"
      },
      {
         "date":"12/31/2009",
         "portfolio":"19.92",
         "sp500":"26.46"
      },
      {
         "date":"12/31/2010",
         "portfolio":"13.59",
         "sp500":"15.06"
      },
      {
         "date":"12/31/2011",
         "portfolio":"-1.58",
         "sp500":"2.11"
      }
    ]
 };</script>        <script>
                var inc = 0;
            
                data = origdata.cDataSet;
                
                data.forEach( function(d) {
                    for (key in d) {
                        if ( key != "date" ) {
                            perfdata[inc]  = { date: parse(d.date) , perf : parseFloat(d[key]), symbol : key };
                            inc = inc + 1;
                        }
                    };
                });
                  
                //if we want to filter only some set of what is there
                //stocks = perfdata.filter(function(d) { return d.symbol in filter; });
                
                // Nest stock values by symbol.
                symbols = d3.nest()
                  .key(function(d) { return d.symbol; })
                  .entries(perfdata);
                
                // Parse dates and numbers. We assume values are sorted by date.
                // Also compute the maximum price per symbol, needed for the y-domain.
                //symbols.forEach(function(s) {
                //    s.values.forEach(function(d) { d.date = parse(d.date); d.price = +d.price; });
                //});
                
                // Sort by maximum price, descending.
                //symbols.sort(function(a, b) { return b.maxPrice - a.maxPrice; });
                
                // Compute the minimum and maximum date across symbols.
                x.domain([
                    d3.min(symbols, function(d) { return d.values[0].date; }),
                    d3.max(symbols, function(d) { return d.values[d.values.length - 1].date; })
                ]);
                
                var g = svg.selectAll("g")
                    .data(symbols)
                    .enter().append("g")
                        .attr("class", "symbol");  
                                
            groupedBar();
            
            function groupedBar() {
                  x = d3.scale.ordinal()
                      .domain(symbols[0].values.map(function(d) { return d.date; }))
                      .rangeBands([0, width - 60], .1);
                
                  var x1 = d3.scale.ordinal()
                      .domain(symbols.map(function(d) { return d.key; }))
                      .rangeBands([0, x.rangeBand()]);
    
                var y0 = Math.max(Math.abs(d3.min(symbols.map(function(d) { return d3.min(d.values.map(function(d) { return d.perf; })); }))), d3.max(symbols.map(function(d) { return d3.max(d.values.map(function(d) { return d.perf; })); })));                
                y
                    .domain([-y0, y0])
                    //.domain([d3.min(symbols.map(function(d) { return d3.min(d.values.map(function(d) { return d.perf; })); })), d3.max(symbols.map(function(d) { return d3.max(d.values.map(function(d) { return d.perf; })); }))])
                    .range([height, 0])
                    .nice();
                
                var yAxis = d3.svg.axis().scale(y).orient("left");                            

                svg.selectAll(".labels")
                    .data(symbols[0].values.map(function(d) { return d.date; }))
                    .enter().append("text")
                        .attr("class", "labels")
                        .attr("text-anchor", "middle")
                        .attr("x", function(d,i) { return x(i) + x.rangeBand() / 2 ; })
                        .attr("y", height / 2 + 15)
                        .text(function(d) {return format(d) })
                        .style("fill-opacity", 1);

                
                  var g = svg.selectAll(".symbol");
                
                  var t = g.transition()
                      .duration(duration);
                      
                    //got working with lots of help but this section particularly dedicated to //stackoverflow.com/questions/10127402/bar-chart-with-negative-values
                  g.each(function(p, j) {
                    d3.select(this).selectAll("rect")
                        .data(function(d) { return d.values; })
                      .enter().append("rect")
                        .attr("x", function(d) { return x(d.date) + x1(p.key); })
                        .attr("y", function(d, i) { return y(Math.max(0, d.perf)); })                        
                        //.attr("y", function(d) { return y(d.perf); })
                        .attr("width", x1.rangeBand())
                        .attr("height", function(d, i) { return Math.abs(y(d.perf) - y(0)); })                        
                        //.attr("height", function(d) { return height - y(d.perf); })
                        .style("fill", color(p.key))
                        .style("fill-opacity", 1e-6)                    
                      .transition()
                        .duration(duration)
                        .style("fill-opacity", 0.8);
                      
                    d3.select(this).selectAll("text")
                        .data(function(d) { return d.values; })
                        .enter().append("text")
                            .attr("class","barlabels")
                            .attr("x", function(d) { return x(d.date) + x1(p.key) + x1.rangeBand() / 2 ; })
                            .attr("y", function(d, i) { return y(d.perf) ; })
                            .attr("text-anchor", "middle")                        
                            .text(function(d) { return d.perf; })
                            .style("fill-opacity", 1e-6)                    
                       .transition()
                        .duration(duration)
                        .style("fill-opacity", 1);
                  });            
                        
                    //svg.append("g")
                    //    .attr("class", "x axis")
                    //    .call(d3.svg.axis().scale(x).orient("bottom"));
                    
                    svg.append("g")
                        .attr("class", "y axis")
                        .call(yAxis);
                    //    .attr("y1", 0)
                    //    .attr("y2", height);
                
            }
            
            function sendtoR() {
                alert("tryingtosend");
                String.prototype.startsWith = function(str){return (this.indexOf(str) === 0);}

                var socket = new WebSocket("ws://localhost:7681", "R");

                try {
                    socket.onopen = function() {
                        document.getElementById("wsdi_status").textContent = " websocket connection opened ";
                        document.getElementById("statustd").style.backgroundColor = "#40ff40";
                    } 
                    
                    socket.onmessage = function got_packet(msg) {
                        if(msg.data=="hello") {
                            alert("got something");
                            socket.send(JSON.stringify(origdata));
                        } else {
                            //svg.remove();
                            //svg
                            d3.select("#svgchart").remove();
                            d3.select("body").selectAll("img").remove();
                            d3.select("body").selectAll("p").remove();
                            d3.select("body").selectAll("footer").remove();      
                            d3.select("body").append("img")
                                .attr("width","850")
                                .attr("height","500")
                                .attr("id","plot")
                                .attr("src",msg.data);
                            d3.select("body")
                                .append("p")
                                    .text("now thanks to R packages websockets and PerformanceAnalytics");                                
                        }
                    }

                    socket.onclose = function(){
                        document.getElementById("wsdi_status").textContent = " websocket connection CLOSED ";
                        document.getElementById("statustd").style.backgroundColor = "#ff4040";
                    }
                }
                catch(ex) {
                    document.getElementById("output").textContent = "Error: " + ex;
                }
            }
        </script>
   <br>
  <footer>
   <aside>
   <small> works best on Chrome <br />acknowledgements</small>
 
    <a href="//d3js.org/"><small>d3.js</small></a>
   </aside>

  </footer>
 </body>
</html>


axys-r-d3-websockets.r

#borrowed significant and substantial portions of code from http://bigcomputing.com/PerformanceAnalytics.R
#see youtube http://www.youtube.com/embed/0iR8Fo0jwW8 for the demo

# R/websockets example
if(any(is.na(packageDescription('caTools'))))
  stop("This demo requires the caTools package.\nRun install.packages('caTools') to install it.\n\n")
if(any(is.na(packageDescription('PerformanceAnalytics'))))
  stop("This demo requires the PerformanceAnalytics package.\nRun install.packages('PerformanceAnalytics') to install it.\n\n")
library('websockets')
library('caTools')
library('quantmod')
library('PerformanceAnalytics')
require('RJSONIO')

#w = createContext(webpage=static_text_service(htmldata))
w = createContext()

# Set up an established (initialization) callback
g = function(DATA, WS, ...)
{
  websocket_write("hello",WS)
  print("established connection")
}
setCallback("established",g, w)

# Set up a receive callback
f = function(DATA, WS, ...)
{
  #get data sent from websocket
  d = tryCatch(rawToChar(DATA),error=function(e) "")
  #convert JSON message to data.frame and eventually xts
  perf <- fromJSON(d)
  perf.df<- as.data.frame(matrix(unlist(fromJSON(d)),ncol=3,byrow=TRUE),stringsAsFactors=TRUE)
  perf.df[,2:3] <- apply(perf.df[,2:3],MARGIN=2,as.numeric)/100
  #name columns
  colnames(perf.df) <- c("date","portfolio","sp500")
  #get as xts so convert dates from %m/%d/%Y to %Y-%m-%d
  perf.xts <- as.xts(perf.df[,2:NCOL(perf.df)],order.by=as.Date(perf.df[,1],format="%m/%d/%Y"))
  f = tempfile()
  jpeg(file=f, width=850,height=500, quality=100)
  devAskNewPage(ask=FALSE)
  charts.PerformanceSummary(perf.xts, colorset = rich6equal, lwd = 2, ylog = TRUE)
  dev.off()
  p <- base64encode(readBin(f,what="raw",n=1e6))
  p <- paste("data:image/jpg;base64,\n",p,sep="")
  websocket_write(paste(p),WS)
  file.remove(f)

  #this will send the dataframe so an object of arrays
  #websocket_write(toJSON(df),WS);
  #try with matrix which sends an array of objects (d3 prefers and handles better)
  #websocket_write(toJSON(as.matrix(df)),WS)
  #websocket_write("got your data; thanks",WS)
}
setCallback("receive",f, w)


cat("\nThe web service will run until <CTRL>+C is pressed.\n")
cat("Open your local web browser to http://localhost:7681\n")
while(TRUE) {
  service(w, timeout=1000L)
  #old service(w)
  #old Sys.sleep(0.05)
}
rm(w)
gc()