January 18, 2016

D3js Scatter Plot in RapidMiner

Continuing on the theme of using D3js to visualize RapidMiner results, this time I show you how to skip putting it into a RapidMiner Server dashboard. I simply borrowed the scatterplot D3js code from mblocks and slapped into a RapidMiner process (see XML below).

For this example, I’m just using the Iris data set but I have tried it with shapefiles and other data. I also use RapidMiner macros to vary the x and y axis. You can control those macros within the context view of RapidMiner.

When you execute the process, it writes two files to a tmp directory, the Iris data set in a data.js file and the actual scatterplot HTML file. The data.js file is called into the HTML file.

Note: you will need some sort of web server to be running so you can render the generated HTML file correcly. Enjoy!

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<process version="6.5.002">
<context>
<input/>
<output/>
<macros>
<macro>
<key>x_axis</key>
<value>a2</value>
</macro>
<macro>
<key>y_axis</key>
<value>a3</value>
</macro>
<macro>
<key>color_column</key>
<value>label</value>
</macro>
</macros>
</context>
<operator activated="true" class="process" compatibility="6.5.002" expanded="true" name="Process">
<process expanded="true">
<operator activated="true" class="text:create_document" compatibility="6.5.000" expanded="true" height="60" name="Create Document (3)" width="90" x="45" y="255">
<parameter key="text" value="&lt;!DOCTYPE html&gt;&#10;&lt;html&gt;&#10;&lt;meta charset=&quot;utf-8&quot;&gt;&#10;&#10;&lt;!-- Example based on http://bl.ocks.org/mbostock/3887118 --&gt;&#10;&lt;!-- Tooltip example from http://www.d3noob.org/2013/01/adding-tooltips-to-d3js-graph.html --&gt;&#10;&#10;&lt;style&gt;&#10;body {&#10;  font: 11px sans-serif;&#10;}&#10;&#10;.axis path,&#10;.axis line {&#10;  fill: none;&#10;  stroke: #000;&#10;  shape-rendering: crispEdges;&#10;}&#10;&#10;.dot {&#10;  stroke: #000;&#10;}&#10;&#10;.tooltip {&#10;  position: absolute;&#10;  width: 200px;&#10;  height: 28px;&#10;  pointer-events: none;&#10;}&#10;&lt;/style&gt;&#10;&lt;body&gt;&#10;&lt;script src=&quot;http://d3js.org/d3.v3.min.js&quot;&gt;&lt;/script&gt;&#10;&#10;&lt;script&gt;&#10;var margin = {top: 20, right: 20, bottom: 30, left: 40},&#10;    width = 960 - margin.left - margin.right,&#10;    height = 500 - margin.top - margin.bottom;&#10;&#10;/* &#10; * value accessor - returns the value to encode for a given data object.&#10; * scale - maps value to a visual display encoding, such as a pixel position.&#10; * map function - maps from data value to display value&#10; * axis - sets up axis&#10; */ &#10;&#10;// setup x &#10;var xValue = function(d) { return d.%{x_axis};}, // data -&gt; value&#10;    xScale = d3.scale.linear().range([0, width]), // value -&gt; display&#10;    xMap = function(d) { return xScale(xValue(d));}, // data -&gt; display&#10;    xAxis = d3.svg.axis().scale(xScale).orient(&quot;bottom&quot;);&#10;&#10;// setup y&#10;var yValue = function(d) { return d.%{y_axis};}, // data -&gt; value&#10;    yScale = d3.scale.linear().range([height, 0]), // value -&gt; display&#10;    yMap = function(d) { return yScale(yValue(d));}, // data -&gt; display&#10;    yAxis = d3.svg.axis().scale(yScale).orient(&quot;left&quot;);&#10;&#10;// setup fill color&#10;var cValue = function(d) { return d.%{color_column};},&#10;    color = d3.scale.category10();&#10;&#10;// add the graph canvas to the body of the webpage&#10;var svg = d3.select(&quot;body&quot;).append(&quot;svg&quot;)&#10;    .attr(&quot;width&quot;, width + margin.left + margin.right)&#10;    .attr(&quot;height&quot;, height + margin.top + margin.bottom)&#10;  .append(&quot;g&quot;)&#10;    .attr(&quot;transform&quot;, &quot;translate(&quot; + margin.left + &quot;,&quot; + margin.top + &quot;)&quot;);&#10;&#10;// add the tooltip area to the webpage&#10;var tooltip = d3.select(&quot;body&quot;).append(&quot;div&quot;)&#10;    .attr(&quot;class&quot;, &quot;tooltip&quot;)&#10;    .style(&quot;opacity&quot;, 0);&#10;&#10;// load data&#10;d3.json(&quot;data.js&quot;, function(error, data) {&#10;&#10;  // change string (from CSV) into number format&#10;  data.forEach(function(d) {&#10;    d.%{x_axis} = +d.%{x_axis};&#10;    d.%{y_axis} = +d.%{y_axis};&#10;//    console.log(d);&#10;  });&#10;&#10;  // don't want dots overlapping axis, so add in buffer to data domain&#10;  xScale.domain([d3.min(data, xValue)-1, d3.max(data, xValue)+1]);&#10;  yScale.domain([d3.min(data, yValue)-1, d3.max(data, yValue)+1]);&#10;&#10;  // x-axis&#10;  svg.append(&quot;g&quot;)&#10;      .attr(&quot;class&quot;, &quot;x axis&quot;)&#10;      .attr(&quot;transform&quot;, &quot;translate(0,&quot; + height + &quot;)&quot;)&#10;      .call(xAxis)&#10;    .append(&quot;text&quot;)&#10;      .attr(&quot;class&quot;, &quot;label&quot;)&#10;      .attr(&quot;x&quot;, width)&#10;      .attr(&quot;y&quot;, -6)&#10;      .style(&quot;text-anchor&quot;, &quot;end&quot;)&#10;      .text(&quot;%{x_axis}&quot;);&#10;&#10;  // y-axis&#10;  svg.append(&quot;g&quot;)&#10;      .attr(&quot;class&quot;, &quot;y axis&quot;)&#10;      .call(yAxis)&#10;    .append(&quot;text&quot;)&#10;      .attr(&quot;class&quot;, &quot;label&quot;)&#10;      .attr(&quot;transform&quot;, &quot;rotate(-90)&quot;)&#10;      .attr(&quot;y&quot;, 6)&#10;      .attr(&quot;dy&quot;, &quot;.71em&quot;)&#10;      .style(&quot;text-anchor&quot;, &quot;end&quot;)&#10;      .text(&quot;%{y_axis}&quot;);&#10;&#10;  // draw dots&#10;  svg.selectAll(&quot;.dot&quot;)&#10;      .data(data)&#10;    .enter().append(&quot;circle&quot;)&#10;      .attr(&quot;class&quot;, &quot;dot&quot;)&#10;      .attr(&quot;r&quot;, 3.5)&#10;      .attr(&quot;cx&quot;, xMap)&#10;      .attr(&quot;cy&quot;, yMap)&#10;      .style(&quot;fill&quot;, function(d) { return color(cValue(d));}) &#10;      .on(&quot;mouseover&quot;, function(d) {&#10;          tooltip.transition()&#10;               .duration(200)&#10;               .style(&quot;opacity&quot;, .9);&#10;          tooltip.html(d[&quot;%{color_column}&quot;] + &quot;&lt;br/&gt; (&quot; + xValue(d) &#10;&#9;        + &quot;, &quot; + yValue(d) + &quot;)&quot;)&#10;               .style(&quot;left&quot;, (d3.event.pageX + 5) + &quot;px&quot;)&#10;               .style(&quot;top&quot;, (d3.event.pageY - 28) + &quot;px&quot;);&#10;      })&#10;      .on(&quot;mouseout&quot;, function(d) {&#10;          tooltip.transition()&#10;               .duration(500)&#10;               .style(&quot;opacity&quot;, 0);&#10;      });&#10;&#10;  // draw legend&#10;  var legend = svg.selectAll(&quot;.legend&quot;)&#10;      .data(color.domain())&#10;    .enter().append(&quot;g&quot;)&#10;      .attr(&quot;class&quot;, &quot;legend&quot;)&#10;      .attr(&quot;transform&quot;, function(d, i) { return &quot;translate(0,&quot; + i * 20 + &quot;)&quot;; });&#10;&#10;  // draw legend colored rectangles&#10;  legend.append(&quot;rect&quot;)&#10;      .attr(&quot;x&quot;, width - 18)&#10;      .attr(&quot;width&quot;, 18)&#10;      .attr(&quot;height&quot;, 18)&#10;      .style(&quot;fill&quot;, color);&#10;&#10;  // draw legend text&#10;  legend.append(&quot;text&quot;)&#10;      .attr(&quot;x&quot;, width - 24)&#10;      .attr(&quot;y&quot;, 9)&#10;      .attr(&quot;dy&quot;, &quot;.35em&quot;)&#10;      .style(&quot;text-anchor&quot;, &quot;end&quot;)&#10;      .text(function(d) { return d;})&#10;});&#10;&#10;&lt;/script&gt;&#10;&lt;/body&gt;&#10;&lt;/html&gt;"/>
<description align="center" color="transparent" colored="false" width="126">D3js Scatterplot script</description>
</operator>
<operator activated="true" class="text:write_document" compatibility="6.5.000" expanded="true" height="76" name="Write Document" width="90" x="179" y="255"/>
<operator activated="true" class="write_file" compatibility="6.5.002" expanded="true" height="60" name="Write File" width="90" x="313" y="255">
<parameter key="filename" value="C:\tmp\D3\IRISscatterplot.html"/>
<description align="center" color="transparent" colored="false" width="126">Write HTML with D3js</description>
</operator>
<operator activated="true" class="retrieve" compatibility="6.5.002" expanded="true" height="60" name="Retrieve Iris" width="90" x="45" y="30">
<parameter key="repository_entry" value="//Samples/data/Iris"/>
<description align="center" color="transparent" colored="false" width="126">Load Iris Data</description>
</operator>
<operator activated="true" class="text:data_to_json" compatibility="6.5.000" expanded="true" height="76" name="Data To JSON" width="90" x="179" y="30">
<parameter key="generate_array" value="true"/>
<description align="center" color="transparent" colored="false" width="126">Convert to JSON</description>
</operator>
<operator activated="true" class="text:write_document" compatibility="6.5.000" expanded="true" height="76" name="Write Document (2)" width="90" x="313" y="30">
<description align="center" color="transparent" colored="false" width="126">Write JSON data for D3plt</description>
</operator>
<operator activated="true" class="write_file" compatibility="6.5.002" expanded="true" height="60" name="Write File (2)" width="90" x="581" y="120">
<parameter key="filename" value="C:\tmp\D3\data.js"/>
<description align="center" color="transparent" colored="false" width="126">JS data file</description>
</operator>
<operator activated="true" class="text:documents_to_data" compatibility="6.5.000" expanded="true" height="76" name="Documents to Data" width="90" x="581" y="30">
<parameter key="text_attribute" value="text"/>
</operator>
<operator activated="true" class="extract_macro" compatibility="6.5.002" expanded="true" height="60" name="Extract Macro" width="90" x="715" y="30">
<parameter key="macro" value="jsonData"/>
<parameter key="macro_type" value="data_value"/>
<parameter key="attribute_name" value="text"/>
<parameter key="example_index" value="1"/>
<list key="additional_macros"/>
</operator>
<connect from_op="Create Document (3)" from_port="output" to_op="Write Document" to_port="document"/>
<connect from_op="Write Document" from_port="file" to_op="Write File" to_port="file"/>
<connect from_op="Write File" from_port="file" to_port="result 1"/>
<connect from_op="Retrieve Iris" from_port="output" to_op="Data To JSON" to_port="example set 1"/>
<connect from_op="Data To JSON" from_port="documents" to_op="Write Document (2)" to_port="document"/>
<connect from_op="Write Document (2)" from_port="document" to_op="Documents to Data" to_port="documents 1"/>
<connect from_op="Write Document (2)" from_port="file" to_op="Write File (2)" to_port="file"/>
<connect from_op="Documents to Data" from_port="example set" to_op="Extract Macro" to_port="example set"/>
<portSpacing port="source_input 1" spacing="0"/>
<portSpacing port="sink_result 1" spacing="0"/>
<portSpacing port="sink_result 2" spacing="0"/>
</process>
  </operator>
</process>


RapidMiner tutorials D3js


Previous post
Extending GIS in RapidMiner My talented coworker and GIS expert, Balázs Bárány, made some amazing progress on extending GIS in RapidMiner. Using Groovy Script, and the Execute
Next post
A day in the Life of a Sales Engineer If you asked me 2 years ago if I’d be working in Sales at a high tech startup, I’d say you were nuts! Fast forward to today and that’s exactly what