The most traditional use case for weather data is displaying forecast details or current conditions for an end user. However, there are tons of other fun ways to integrate weather data into applications. Using our weather API, I’ll show you how to capture the greatest temperature delta on a monthly basis in Minnesota throughout 2017. Why am I doing this? Well, I simply wanted to know how large our temperature difference was on a monthly basis.
The first component of this project will require us to build out a query that searches the entire state on each day for the highest and lowest temperature. We will need 2 separate queries: one to sort by the highest temperature recorded and one to sort by the lowest temperature recorded. Other than sorting, each request will be identical.
We will hit the observations/summary endpoint and use the search action (because we will search the entire state):
1 |
api.aerisapi.com/observations/summary/search? |
Next, we can add parameters such as date, state, and client credentials. With the date values, I’ll use variables since these change for each query:
1 |
from=${date}&to=${date}&query=state:mn&client_id=CLIENT_ID&client_secret=CLIENT_SECRET |
I’m also going to utilize the fields parameter to limit the output:
1 |
&fields=id,place,periods.summary.dateTimeISO,periods.summary.temp.maxF,periods.summary.temp.minF |
The last parameter will be sorting. Within the observations/summary endpoint, we can see a couple temperature specific sorting parameters. I’ll need to sort by the mint ascending parameter for one query and maxt descending for the other query.
1 2 3 4 5 |
// Low Temps: &sort=mint:1 // High Temps: &sort=maxt:-1 |
We have all the pieces for the API request now so we can concatenate them to make our queries:
1 2 3 4 5 |
// Low Temps Query: api.aerisapi.com/observations/summary/search?from=${date}&to=${date}&query=state:mn&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&fields=id,place,periods.summary.dateTimeISO,periods.summary.temp.maxF,periods.summary.temp.minF&sort=mint:1 // High Temps Query: api.aerisapi.com/observations/summary/search?from=${date}&to=${date}&query=state:mn&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&fields=id,place,periods.summary.dateTimeISO,periods.summary.temp.maxF,periods.summary.temp.minF&sort=maxt:-1 |
To make this even simpler we can use the batch feature to combine these queries into a single query.* There are several parameters that are used by both queries such as state, date, fields, and client credentials so we can include those outside of the requests= parameter. Within the requests= parameter we will include the endpoints and sorting technique. Also, remember we’ll need to encode the value for the requests parameter. Here’s the full batch request:
1 |
api.aerisapi.com/batch?from=${date}&to=${date}&query=state:mn&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&fields=id,place,periods.summary.dateTimeISO,periods.summary.temp.maxF,periods.summary.temp.minF&requests=%2Fobservations%2Fsummary%2Fsearch%3Fsort%3Dmaxt%3A-1%2C%2Fobservations%2Fsummary%2Fsearch%3Fsort%3Dmint%3A1 |
* This will still count as 2 separate API hits in a single batch request.
Using NodeJS, we can run the script locally and output to a CSV file that will be used in a spreadsheet application. We need to use a request module that would be able to handle promises so I went with request-promise-native. Using async / await, we’re able to run the queries asynchronously in an attempt to stay below the Aeris account’s minute rate.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
const request = require('request-promise-native'); async function datesLoop() { for (let i = 0; i <= 364; i++) { const startDate = new Date(1483282841000); // 2017-01-01 let newDate = new Date(startDate.setDate(startDate.getDate() + i)); let formattedDate = { year: newDate.getFullYear(), month: newDate.getMonth() + 1, day: newDate.getDate(), full: function () { return this.year + '-' + this.month + '-' + this.day } }; let batchOptions = { method: 'GET', url: 'https://api.aerisapi.com/batch', qs: { query: `state:mn`, from: `${formattedDate.full()}`, to: `${formattedDate.full()}`, fields: `id,place,periods.summary.dateTimeISO,periods.summary.temp.maxF,periods.summary.temp.minF`, client_id: `yFwjmw8MSKxWmUspHP63J`, client_secret: `Y1ic4Js6acfZfsG7uPY5O6KCrv4vUQ90Vy5HfVOq`, requests: `%2Fobservations%2Fsummary%2Fsearch%3Fsort%3Dmint%3A1%2C%2Fobservations%2Fsummary%2Fsearch%3Fsort%3Dmaxt%3A-1` } }; await queryAPI(batchOptions) } } async function queryAPI(urlOptions) { const body = await request(urlOptions); const json = JSON.parse(body); writeToCsv(json); } function writeToCsv(json) { let lowestMinResponse = json.response.responses[0].response[0]; let highestMaxResponse = json.response.responses[1].response[0]; let state = lowestMinResponse.place.state; let date = lowestMinResponse.periods[0].summary.dateTimeISO.substr(0,10); let lowTemp = lowestMinResponse.periods[0].summary.temp.minF; let highTemp = highestMaxResponse.periods[0].summary.temp.maxF; console.log([state,date,lowTemp,highTemp].join(",")) } // WRITE COLUMN NAMES console.log([ 'state', 'date', 'coldestTemp', 'hottestTemp' ].join(',')); datesLoop() .then(() => { console.error('COMPLETE!'); }); |
Once the query is built by setting the date, it gets sent off to the queryAPI() function which will trigger the writeToCsv() function. As the script initially loads, we write the column names and kick off the datesLoop() function. Simple enough, right? Once the script is complete, we have data that will help us derive the temperature delta by month.
Now that we have the data, we’re going to need some fancy spreadsheet skills to help paint the full picture. Microsoft Excel or Google Sheets should do the trick – I went with Google Sheets this time around. Using the Named Ranges feature, I created 12 separate data ranges based on the month:
=”
Next, I’ll create a separate table to identify the lowest and highest temperature for each month. Using the Named Ranges along with a simple =MIN() and =MAX() function within Sheets, I can easily return the expected values. Finally, we can add the Delta column by subtracting the high from the low:
Month | Lowest Temp | Highest Temp | Delta |
---|---|---|---|
January | -38 | 48 | 86 |
February | -29 | 70 | 99 |
March | -17 | 73 | 90 |
April | 16 | 84 | 68 |
May | 21 | 91 | 70 |
June | 31 | 99 | 68 |
July | 34 | 99 | 65 |
August | 30 | 90 | 60 |
September | 30 | 95 | 65 |
October | 1 | 82 | 81 |
November | -15 | 66 | 81 |
December | -36 | 64 | 100 |
The temperature delta will be relatively straightforward. First, let’s sort the delta by greatest number which puts the month of December in 1st place at 100. Go, December! In Sheets, select your data range and then Insert > Chart in the top menu. By default, Sheets is smart enough to select Column Chart for us so I’ll leave it at that. However, I will make some style changes to the chart to pretty it up. Here’s our final chart:
Temperature Delta by Month in 2017
As you can see, us Minnesotans endure quite the range of temperatures in the colder months. No wonder we’re notorious for being snowbirds! Meanwhile, the summer months are clearly more consistent which keeps us sane.
The Delta table is nice and all, but let’s take it one step further and create a table that will help us generate a bar chart for the highs and lows for each month. We can accomplish this with a stacked bar chart which will require 3 more columns in our table:
All of these can be achieved with the spreadsheets built-in IF statements.
Why are we doing this? Good question! When we’re graphing the temperature difference we actually won’t be using any of the original values we pulled from the API. We’ll be using these new values to stack bars and hide others. Of course, this calculation could have been done in our script, but then we wouldn’t get to have as much fun in the spreadsheet. Here’s the final result:
Month | Low Temp | High Temp | Negative Low | Positive Low | High Unless Low is Positive |
---|---|---|---|---|---|
January | -38 | 48 | -38 | 0 | 48 |
February | -29 | 70 | -29 | 0 | 70 |
March | -17 | 73 | -17 | 0 | 73 |
April | 16 | 84 | 0 | 16 | 68 |
May | 21 | 91 | 0 | 21 | 70 |
June | 31 | 99 | 0 | 31 | 68 |
July | 34 | 99 | 0 | 34 | 65 |
August | 30 | 90 | 0 | 30 | 60 |
September | 30 | 95 | 0 | 30 | 65 |
October | 1 | 82 | 0 | 1 | 81 |
November | -15 | 66 | -15 | 0 | 66 |
December | -36 | 64 | -36 | 0 | 64 |
We’ll kick off our next chart by going to Insert > Chart from the top menu. Under the Chart type, select the stacked bar chart. Under data range select column A and then Add another range which will be columns D, E, and F. Here’s what we have so far:
Initial Chart
Remember earlier when I mentioned we were going to hide some values? We want to hide the red bars in the chart above because the end of the bar will represent where the low will start when the low was positive. In the Chart Editor go to Customize > Series. Here we have the option to customize all series, or a specific series. Select the if low positive series and mark the color as none. While we’re here we can make sure the other two series have the same color so the chart flows. After some styling updates, here’s our final product:
Temperature Differences by Month 2017
Now we have a handy visualization for the temperature spread and temperature delta for each month! Welcome to Minnesota, where it’s brutally cold in the winter and oppressively hot in the summer. That’s good ol’ Minnesota for you.
Sign up for the weather API today and see what fun visualizations you can create!
No comments yet.
Be the first to respond to this article.