Neural Market Trends |||

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>
Up next 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 Experimenting Just a quick post. I’m experimenting with adding a D3js type of dashboard to this site. I wrote a simple process to pull the closing prices of the
Latest posts Phone Addiction Version 12 Launches Today! Machine Learning Making Pesto Tastier 5 Dangerous Things You Should Let Your Kids Do The Pyschology of Writing TensorFlow and High Level APIs Driving Marketing Performance with H2O Driverless AI Machine Learning and Data Munging in H2O Driverless AI with datatable Making AI Happen Without Getting Fired Latest Musings from a Traveling Sales Engineer The Night before H2O World 2019 Why Forex Trading is Frustrating Functional Programming in Python Automatic Feature Engineering with Driverless AI Ray Dalio's Pure Alpha Fund What's new in Driverless AI? Latest Writings Elsewhere - December 2018 House Buying Guide for Millennials Changing Pinboard Tags with Python Automate Feed Extraction and Posting it to Twitter Flux: A Machine Learning Framework for Julia Getting Started in Data Science Part 2 Makers vs Takers How Passive Investing Saved My Life Startups and Open Source The Process of Writing H2O AI World 2018 in London Ray Dalio's Pure Alpha Fund Isolation Forests in H2O.ai Living the Dream? Humility and Equanimity in Sales