{"id":1471,"date":"2014-10-10T14:40:42","date_gmt":"2014-10-10T13:40:42","guid":{"rendered":"http:\/\/blogs.it.ox.ac.uk\/acit-rs-team\/?p=1471"},"modified":"2014-10-10T14:40:42","modified_gmt":"2014-10-10T13:40:42","slug":"how-to-create-a-bubble-chart-from-a-google-spreadsheet-using-d3-js","status":"publish","type":"post","link":"https:\/\/blogs.it.ox.ac.uk\/acit-rs-team\/2014\/10\/10\/how-to-create-a-bubble-chart-from-a-google-spreadsheet-using-d3-js\/","title":{"rendered":"How to: create a bubble chart from a Google Spreadsheet using D3.js"},"content":{"rendered":"<p>Earlier in this series I discussed how to <a title=\"How to: get data out of a Google spreadsheet using JSONP\" href=\"http:\/\/blogs.it.ox.ac.uk\/acit-rs-team\/2014\/10\/08\/how-to-get-data-out-of-a-google-spreadsheet-using-jsonp\/\">get data out of a Google Spreadsheet in JSON format using an API call<\/a>, and how to <a title=\"How to: convert Google Spreadsheet JSON data into a simple two-dimensional array\" href=\"http:\/\/blogs.it.ox.ac.uk\/acit-rs-team\/2014\/10\/09\/how-to-convert-google-spreadsheet-json-data-into-a-simple-two-dimensional-array\/\">convert the JSON data into an array<\/a>. Now I&#8217;m going to talk about how to visualise the data as a bubble chart on a web page, using the fantastically powerful JavaScript library <a href=\"http:\/\/d3js.org\/\">D3.js,<\/a> aka <em>Data Driven Documents<\/em>.<\/p>\n<p>For this exercise I&#8217;ve created a Google Spreadsheet representing some information about a fictional group of people with a count of their interactions. You can <a href=\"https:\/\/docs.google.com\/spreadsheets\/d\/1Mu_vculJGX5vLBRL69PhRRYsdxwgccZf6vHtDNYqRWk\/pubhtml\">see the spreadsheet here<\/a>.<\/p>\n<p>Following the instructions in the previous How To guides we can get this data using JSONP; you can <a href=\"https:\/\/spreadsheets.google.com\/feeds\/cells\/1Mu_vculJGX5vLBRL69PhRRYsdxwgccZf6vHtDNYqRWk\/od6\/public\/values?alt=json-in-script&amp;callback=render\">see the result for yourself here<\/a>.<\/p>\n<p>So, having got the source data, how are we going to visualise it?<\/p>\n<p>Well, the first step is to transform the data once again into a structure that is more suitable for the D3.js techniques we want to use. In this case we&#8217;re creating a bubble chart using a method called <strong>d3.layout.pack()<\/strong>. This takes a <em>tree<\/em> structure of <em>objects<\/em>, and fits them into a volume based on the <em>value<\/em>\u00a0property of each <em>leaf<\/em> node. In our example, the value we&#8217;re interested in is the number of interactions &#8211; so team members with more interactions will be represented by larger bubbles within the visualisation.<\/p>\n<p>So how do we do that? Well, the easiest approach is to iterate over each row in the data, and create an object for it with a <em>name<\/em>, a <em>value<\/em> and a <em>group<\/em>. (The group property in this case is the team the person belongs to.) These &#8220;leaf&#8221; objects can then be added to a &#8220;root&#8221; object to make a tree in JavaScript.<\/p>\n<p>The code for this looks like so:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n    var root = {};\r\n    root.name = &quot;Interactions&quot;;\r\n    root.children = new Array();\r\n    for (i=0;i&lt;dataframe.length;i++){\r\n      var item = {};\r\n      item.name = dataframe&#x5B;i]&#x5B;0];\r\n      item.value = Number(dataframe&#x5B;i]&#x5B;1]);\r\n      item.group = dataframe&#x5B;i]&#x5B;2];\r\n      root.children.push(item);\r\n    }\r\n<\/pre>\n<p>So, taking it one line at a time &#8211; we create a <em>root<\/em> object, give it a name, and create a new empty array inside it called <em>children<\/em>. We then we go through each row in the dataframe and create an <em>item<\/em> object for each one, mapping the name, value and group properties to the correct columns in the spreadsheet. Each item is added to the <em>children<\/em> array.<\/p>\n<p>We now have a tree of objects, each of which has a <em>name<\/em>, a\u00a0<em>value<\/em> and \u00a0a <em>group<\/em>.<\/p>\n<p>How do we create a nice-looking bubble chart with them?<\/p>\n<p>First we set up the\u00a0<strong>d3.layout.pack<\/strong> function so it can calculate the size and position of the bubbles. We do this using:<\/p>\n<pre>var bubble = d3.layout.pack().sort(null).size([960,960]).padding(1.5);<\/pre>\n<p>If you were to now call &#8230;<\/p>\n<pre>bubble.nodes(root)<\/pre>\n<p>&#8230; and take a look at the output, you would see each &#8220;leaf&#8221; object \u00a0now has several new properties for &#8220;x&#8221;, &#8220;y&#8221; and &#8220;r&#8221;. The &#8220;x&#8221; and &#8220;y&#8221; properties are where within the chart to position the bubble, for the object and the &#8220;r&#8221; property is the radius of the bubble.<\/p>\n<p>(How this is actually drawn is up to you &#8211; you could equally well take this information and draw the whole thing using hexagons or squares or spheres. But lets stick to circles for now.)<\/p>\n<p>Next we need to create a graphic for the chart in our HTML page. D3 can make this for us like so:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n    var svg = d3.select(&quot;body&quot;)\r\n                .append(&quot;svg&quot;)\r\n                .attr(&quot;width&quot;,960)\r\n                .attr(&quot;height&quot;, 960)\r\n                .attr(&quot;class&quot;,&quot;bubble&quot;);\r\n<\/pre>\n<p>For each &#8220;leaf&#8221; we then need to create a graphical element. D3.js uses a very clever approach for this:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n\r\n    var node = svg.selectAll(&quot;.node&quot;)\r\n                  .data(bubble.nodes(root)\r\n                  .filter(function(d){ return !d.children;}))\r\n                  .enter()\r\n                  .append(&quot;g&quot;)\r\n                  .attr(&quot;class&quot;,&quot;node&quot;)\r\n                  .attr(&quot;transform&quot;, function(d) { return &quot;translate(&quot; + d.x + &quot;,&quot; + d.y + &quot;)&quot;; });\r\n<\/pre>\n<p>The key thing here is the <strong>data()<\/strong> method. We pass this the <em>bubble<\/em> layout we created earlier, and ask it to create the nodes based on our <em>root<\/em> object. (We also filter out the root node itself as we&#8217;re not interested in drawing that, just the individual leaf nodes.)\u00a0The <strong>enter()<\/strong> method is then called for each leaf node in the tree, which appends a &lt;g&gt; element to the &lt;svg&gt; element in our HTML document, and applies the <strong>transform<\/strong> property to it to place it at the correct <em>x<\/em> and <em>y<\/em> coordinates within the chart.<\/p>\n<p>This still doesn&#8217;t draw anything interesting, so lets make some circles for each node, and give them a label:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n   var colour = d3.scale.category10();\r\n   node.append(&quot;circle&quot;)\r\n       .attr(&quot;r&quot;, function(d) { return d.r; })\r\n       .style(&quot;fill&quot;, function(d) { return colour(d.group); });\r\n   node.append(&quot;text&quot;)\r\n       .attr(&quot;dy&quot;, &quot;.3em&quot;)\r\n       .style(&quot;text-anchor&quot;, &quot;middle&quot;)\r\n       .text(function(d) { return d.name; });\r\n<\/pre>\n<p>The result of all this is a nice diagram! Click to view it full size; you can also see the <a href=\"http:\/\/scottbw.github.io\/d3js-bubble-example\/\">live version here<\/a>.<\/p>\n<p><a href=\"http:\/\/blogs.it.ox.ac.uk\/acit-rs-team\/files\/2014\/10\/bubble_chart.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-1475\" alt=\"A bubble chart\" src=\"http:\/\/blogs.it.ox.ac.uk\/acit-rs-team\/files\/2014\/10\/bubble_chart-300x237.png\" width=\"300\" height=\"237\" srcset=\"https:\/\/blogs.it.ox.ac.uk\/acit-rs-team\/files\/2014\/10\/bubble_chart-300x237.png 300w, https:\/\/blogs.it.ox.ac.uk\/acit-rs-team\/files\/2014\/10\/bubble_chart.png 921w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>The <a href=\"https:\/\/github.com\/scottbw\/d3js-bubble-example\/\">complete source code for this How To guide can be found on Github<\/a>.<\/p>\n<p>If you&#8217;d like to know more about data visualisation, you can get in touch with\u00a0us at\u00a0<a href=\"mailto:researchsupport@it.ox.ac.uk\">researchsupport@it.ox.ac.uk<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Earlier in this series I discussed how to get data out of a Google Spreadsheet in JSON format using an API call, and how to convert the JSON data into an array. Now I&#8217;m going to talk about how to &hellip; <a href=\"https:\/\/blogs.it.ox.ac.uk\/acit-rs-team\/2014\/10\/10\/how-to-create-a-bubble-chart-from-a-google-spreadsheet-using-d3-js\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":245,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[38150],"tags":[],"class_list":["post-1471","post","type-post","status-publish","format-standard","hentry","category-data-modelling-and-migration"],"_links":{"self":[{"href":"https:\/\/blogs.it.ox.ac.uk\/acit-rs-team\/wp-json\/wp\/v2\/posts\/1471","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.it.ox.ac.uk\/acit-rs-team\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.it.ox.ac.uk\/acit-rs-team\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.it.ox.ac.uk\/acit-rs-team\/wp-json\/wp\/v2\/users\/245"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.it.ox.ac.uk\/acit-rs-team\/wp-json\/wp\/v2\/comments?post=1471"}],"version-history":[{"count":9,"href":"https:\/\/blogs.it.ox.ac.uk\/acit-rs-team\/wp-json\/wp\/v2\/posts\/1471\/revisions"}],"predecessor-version":[{"id":1481,"href":"https:\/\/blogs.it.ox.ac.uk\/acit-rs-team\/wp-json\/wp\/v2\/posts\/1471\/revisions\/1481"}],"wp:attachment":[{"href":"https:\/\/blogs.it.ox.ac.uk\/acit-rs-team\/wp-json\/wp\/v2\/media?parent=1471"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.it.ox.ac.uk\/acit-rs-team\/wp-json\/wp\/v2\/categories?post=1471"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.it.ox.ac.uk\/acit-rs-team\/wp-json\/wp\/v2\/tags?post=1471"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}