{"id":2230,"date":"2022-01-25T17:48:39","date_gmt":"2022-01-25T17:48:39","guid":{"rendered":"https:\/\/lvboard.infostore.in.ua\/?p=2230"},"modified":"2022-01-25T17:48:39","modified_gmt":"2022-01-25T17:48:39","slug":"how-to-visualize-weather-data-with-d3-js","status":"publish","type":"post","link":"https:\/\/lvboard.infostore.in.ua\/?p=2230","title":{"rendered":"How to Visualize Weather Data with D3.js"},"content":{"rendered":"\n<p>What plans would you make if you knew it was going to rain tomorrow?<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>This can be a crucial question to ask yourself when it comes to planning your personal and day-to-day business activities.<\/p>\n\n\n\n<p>For example, I have a friend who runs an app-based laundry business in Lagos, Nigeria. He relies heavily on sunshine, and sometimes it rains, or there&#8217;s just no sunshine. On those days, business is very bad.<\/p>\n\n\n\n<p>But what if he knew it was going to rain the next day or in 6 hours? That would help him plan things well in advance and prevent delays in orders. But where can he get such information?<\/p>\n\n\n\n<p>That&#8217;s where the Tomorrow.io&nbsp;<a href=\"https:\/\/www.tomorrow.io\/weather-api\/\">weather API<\/a>&nbsp;comes in. The weather API provides us with accurate and fast weather data in real time, like precipitation probability, amount of rainfall, temperature, wind speed, and more.<\/p>\n\n\n\n<p>Such information is very useful to businesses across various industries like transportation, agriculture, and, in my friend&#8217;s case, laundry shops.<\/p>\n\n\n\n<p>Also, the weather data from this API can be easily integrated into your project or any program you are working with. The best part \u2013 the free version of the API is extremely powerful on its own, so that&#8217;s what we&#8217;ll use today.<\/p>\n\n\n\n<p>In this article, we&#8217;ll use the Tomorrow.io weather API and&nbsp;<a href=\"https:\/\/d3js.org\/\">D3.js<\/a>&nbsp;to forecast and visualize the precipitation probability of a particular location on a line chart. A service like this would allow my friend to tell on which days of the week it is likely to rain.<\/p>\n\n\n\n<h2 id=\"project-requirements\">Project Requirements<\/h2>\n\n\n\n<p>What do you need to continue in this tutorial? Basic knowledge of JavaScript and D3.js is required.<\/p>\n\n\n\n<p>I suggest reading a&nbsp;<a href=\"https:\/\/www.freecodecamp.org\/news\/d3js-tutorial-data-visualization-for-beginners\/\">beginner&#8217;s guide to D3.js<\/a>&nbsp;if you want to refresh your memory before going further.<\/p>\n\n\n\n<h2 id=\"getting-started\">Getting Started<\/h2>\n\n\n\n<p>First, create an HTML file, and add the latest library of&nbsp;<code>d3.js<\/code>&nbsp;to the HTML file. Also, create an empty&nbsp;<code>svg<\/code>&nbsp;element, like so:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n  &lt;head&gt;\n    &lt;meta charset=\"UTF-8\" \/&gt;\n    &lt;meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" \/&gt;\n    &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" \/&gt;\n    &lt;title&gt;Tomorrow.io Rainfall probability&lt;\/title&gt;\n    &lt;script src=\"https:\/\/d3js.org\/d3.v7.min.js\"&gt;&lt;\/script&gt;\n  &lt;\/head&gt;\n  &lt;body&gt;\n    &lt;svg&gt;&lt;\/svg&gt;\n  &lt;\/body&gt;\n  &lt;script src=\"index.js\"&gt;&lt;\/script&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<h2 id=\"how-to-set-up-the-margins\">How to Set Up the Margins<\/h2>\n\n\n\n<p>At some point, our visualizations will need some space (margins). It is a convention in&nbsp;<code>d3.js<\/code>&nbsp;to set up the&nbsp;<strong>margin convention<\/strong>.<\/p>\n\n\n\n<p>For this, you need to define the margins for the four sides, create an&nbsp;<code>index.js<\/code>&nbsp;file, and add the following:<\/p>\n\n\n\n<p><code>const margin = { left: 120, right: 30, top: 60, bottom: 30 }<\/code><\/p>\n\n\n\n<p>Now, let&#8217;s set the width and viewBox of our SVG element. This will help make it responsive.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const width = document.querySelector(\"body\").clientWidth,\n  height = 500;\n\nconst svg = d3.select(\"svg\").attr(\"viewBox\", &#91;0, 0, width, height]);<\/code><\/pre>\n\n\n\n<h2 id=\"how-to-define-the-scales\">How to Define the Scales<\/h2>\n\n\n\n<p>The d3.scale function takes in data as input and returns a visual value in pixels. d3.scale needs to be set with a&nbsp;<strong>domain<\/strong>&nbsp;and a&nbsp;<strong>range.<\/strong>&nbsp;The domain sets a LIMIT for the data we are trying to represent visually.<\/p>\n\n\n\n<p>As seen above, we need to set the range of the scales. We&#8217;ll set the&nbsp;<code>domain<\/code>&nbsp;once we fetch our data:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const x_scale = d3.scaleTime().range(&#91;margin.left, width - margin.right]);\nconst y_scale = d3.scaleLinear().range(&#91;height - margin.bottom - margin.top, margin.top]);<\/code><\/pre>\n\n\n\n<h2 id=\"how-to-add-a-title-and-labels\">How to Add a Title and Labels<\/h2>\n\n\n\n<p>Next, we need to add a title and labels to our visualizations. This is useful for explaining our graph to our users.<\/p>\n\n\n\n<p>Edit your&nbsp;<code>script.js<\/code>&nbsp;and add the following code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ labels\nconst x_label = \"Time\";\nconst y_label = \"Rainfall Probability\";\nconst location_name = \"Lagos Nigeria\";\n\n\/\/ add title\nsvg\n  .append(\"text\")\n  .attr(\"class\", \"svg_title\")\n  .attr(\"x\", (width - margin.right + margin.left) \/ 2)\n  .attr(\"y\", margin.top \/ 2)\n  .attr(\"text-anchor\", \"middle\")\n  .style(\"font-size\", \"22px\")\n  .text(`${y_label} of ${location_name}`);\n\/\/ add y label\nsvg\n  .append(\"text\")\n  .attr(\"text-ancho\", \"middle\")\n  .attr(\n    \"transform\",\n    `translate(${margin.left - 70}, ${\n      (height - margin.top - margin.bottom + 180) \/ 2\n    }) rotate(-90)`\n  )\n  .style(\"font-size\", \"26px\")\n  .text(y_label);\n\/\/ add x label\nsvg\n  .append(\"text\")\n  .attr(\"class\", \"svg_title\")\n  .attr(\"x\", (width - margin.right + margin.left) \/ 2)\n  .attr(\"y\", height - margin.bottom - margin.top + 60)\n  .attr(\"text-anchor\", \"middle\")\n  .style(\"font-size\", \"26px\")\n  .text(x_label);<\/code><\/pre>\n\n\n\n<p>With the above-added title and labels, the preview looks like this:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img src=\"https:\/\/paper-attachments.dropbox.com\/s_80A2ED9660649A0944547FE32AE888AF070E268C15D560C813DD3420036CDBBE_1638557381465_tomorrow.io-demo1.png\" alt=\"Added titles and labels to our visualization\"\/><\/figure>\n\n\n\n<h2 id=\"how-to-create-the-line-chart\">How to Create the Line Chart<\/h2>\n\n\n\n<p>Here, the first thing we&#8217;ll need to do is to generate the&nbsp;<a href=\"https:\/\/sharkcoder.com\/data-visualization\/d3-line-chart\">path<\/a>&nbsp;for our chart. D3.js provides a&nbsp;<code>.line()<\/code>&nbsp;method that pretty much generates the line path for you. Let&#8217;s add the line generator:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const start_time = (d) =&gt; new Date(d.startTime);\nconst temperature = (d) =&gt; +d.values.precipitationProbability;\n\nconst line_generator = d3.line()\n  .x((d) =&gt; x_scale(start_time(d)))\n  .y((d) =&gt; y_scale(temperature(d)))\n  .curve(d3.curveBasis);<\/code><\/pre>\n\n\n\n<p>Now that we have defined our line generator, let&#8217;s go ahead and fetch our data.<\/p>\n\n\n\n<h2 id=\"how-to-fetch-data-from-the-tomorrow-io-weather-api\">How to Fetch Data from the Tomorrow.io Weather API<\/h2>\n\n\n\n<p>D3 provides us with a&nbsp;<code>.json()<\/code>&nbsp;method to fetch JSON data from an API or a local file.<\/p>\n\n\n\n<p>Before you can fetch data using the Tomorrow.io weather API, you&#8217;ll need a secret access token. To get this token, all you need to do is create an account with&nbsp;<a href=\"https:\/\/www.tomorrow.io\/\">Tomorrow.io<\/a>. Yes, it&#8217;s that easy.<\/p>\n\n\n\n<p>Once you have created your account, go ahead and log in. Then, on your&nbsp;<a href=\"https:\/\/app.tomorrow.io\/development\/keys\">dashboard<\/a>, you should see your API secret token:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img src=\"https:\/\/paper-attachments.dropbox.com\/s_80A2ED9660649A0944547FE32AE888AF070E268C15D560C813DD3420036CDBBE_1638566467761_tomorrow.io-demo2.png.png\" alt=\"s_80A2ED9660649A0944547FE32AE888AF070E268C15D560C813DD3420036CDBBE_1638566467761_tomorrow.io-demo2.png\"\/><\/figure>\n\n\n\n<p>Add the following code to fetch the data:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const lat = 6.465422; \/\/ latitude of Lagos, Nigeria\nconst long = 3.406448; \/\/ Longitude of Lagos, Nigeria\n\nconst api_key = \"your-api-key-here\";\n\nconst url = `https:\/\/api.tomorrow.io\/v4\/timelines?location=${lat},${long}&amp;fields=snowAccumulation,precipitationProbability,precipitationType&amp;timesteps=1h&amp;units=metric&amp;apikey=${api_key}`;\n\nd3.json(url).then(({ data }) =&gt; {\n  const d = data.timelines&#91;0].intervals;\n  console.log(d)\n});<\/code><\/pre>\n\n\n\n<p>Here is an example of the JSON data returned from that fetch:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"data\": {\n    \"timelines\": &#91;\n      {\n        \"timestep\": \"1h\",\n        \"startTime\": \"2021-12-03T13:00:00Z\",\n        \"endTime\": \"2021-12-08T01:00:00Z\",\n        \"intervals\": &#91;\n          {\n            \"startTime\": \"2021-12-03T13:00:00Z\",\n            \"values\": {\n              \"snowAccumulation\": 0,\n              \"precipitationProbability\": 0,\n              \"precipitationType\": 0\n            }\n          },\n          \/\/ 108 more data\n        ]\n      }\n    ]\n  }\n}<\/code><\/pre>\n\n\n\n<p>Now that we&#8217;ve fetched our data, let&#8217;s generate our line chart:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>d3.json(url).then(({ data }) =&gt; {\n  const d = data.timelines&#91;0].intervals;\n  \n\/\/ set the domain \n  x_scale.domain(d3.extent(d, start_time)).nice(ticks);\n  y_scale.domain(d3.extent(d, temperature)).nice(ticks);\n  \/\/ add the line path\n  svg\n    .append(\"path\")\n    .attr(\"fill\", \"none\")\n    .attr(\"stroke\", \"steelblue\")\n    .attr(\"stroke-width\", 4)\n    .attr(\"d\", line_generator(d)); \/\/ generate the path\n});<\/code><\/pre>\n\n\n\n<p>The above code gives us a basic chart:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img src=\"https:\/\/paper-attachments.dropbox.com\/s_80A2ED9660649A0944547FE32AE888AF070E268C15D560C813DD3420036CDBBE_1638560607910_tomorrow.io-demo3.png\" alt=\"s_80A2ED9660649A0944547FE32AE888AF070E268C15D560C813DD3420036CDBBE_1638560607910_tomorrow.io-demo3\"\/><\/figure>\n\n\n\n<h2 id=\"how-to-add-the-axes\">How to Add the Axes<\/h2>\n\n\n\n<p>Even with the above line chart, you will have a hard time knowing exactly which day or hour has the highest possibility of rainfall.<\/p>\n\n\n\n<p>We can resolve this by adding the time and rainfall probability (in %) axes.<\/p>\n\n\n\n<p>First, define the axes just below your scales:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const ticks = 10;\nconst x_axis = d3.axisBottom()\n  .scale(x_scale)\n  .tickPadding(10)\n  .ticks(ticks)\n  .tickSize(-height + margin.top * 2 + margin.bottom);\nconst y_axis = d3.axisLeft()\n  .scale(y_scale)\n  .tickPadding(5)\n  .ticks(ticks, \".1\")\n  .tickSize(-width + margin.left + margin.right);\n\n\/\/ format our ticks to get accurate %\ny_axis.tickFormat((d) =&gt; {\n  if (!Number.isInteger(d)) {\n    d = decimalFormatter(d);\n  }\n  return d + \"%\";\n});<\/code><\/pre>\n\n\n\n<p>Finally, let&#8217;s add our axis on the SVG element:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ append x axis\n  svg\n    .append(\"g\")\n    .attr(\"transform\", `translate(0,${height - margin.bottom - margin.top})`)\n    .call(x_axis);\n\n  \/\/ add y axis\n  svg\n    .append(\"g\")\n    .attr(\"transform\", `translate(${margin.left},0)`)\n    .call(y_axis);<\/code><\/pre>\n\n\n\n<p>With the axis added, our line chart now looks like this:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img src=\"https:\/\/paper-attachments.dropbox.com\/s_80A2ED9660649A0944547FE32AE888AF070E268C15D560C813DD3420036CDBBE_1638561615864_tomorrow.io-demo4.png\" alt=\"Tomorrow.io precipitation probality of lagos, Nigeria. December 03, 2021\"\/><\/figure>\n\n\n\n<p>That&#8217;s much better! You can now tell which day and hour has the highest probability of rainfall.<\/p>\n\n\n\n<p>The full code and demo for this example is hosted on Codepen:https:\/\/codepen.io\/Spruce_khalifa\/embed\/preview\/vYeNKRg?default-tabs=js%2Cresult&amp;height=300&amp;host=https%3A%2F%2Fcodepen.io&amp;slug-hash=vYeNKRg<a href=\"https:\/\/codepen.io\/Spruce_khalifa\/pen\/vYeNKRg\">Source<\/a><\/p>\n\n\n\n<h2 id=\"conclusion\">Conclusion<\/h2>\n\n\n\n<p>With the power of D3.js combined with the Tomorrow.io weather API, we can create visualizations that help users solve weather-related issues affecting their businesses.<\/p>\n\n\n\n<p>I hope you found this tutorial helpful.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>What plans would you make if you knew it was going to rain tomorrow?<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[30],"tags":[175],"_links":{"self":[{"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/posts\/2230"}],"collection":[{"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2230"}],"version-history":[{"count":1,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/posts\/2230\/revisions"}],"predecessor-version":[{"id":2231,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/posts\/2230\/revisions\/2231"}],"wp:attachment":[{"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2230"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2230"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2230"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}