官术网_书友最值得收藏!

Loading in data

Go back to main.js. We need to get our data in somehow, and I'll show you far better ways of doing this later on, but let's work through the pain and do this the bad, old way--using XMLHttpRequest:

const req = new window.XMLHttpRequest(); 
req.addEventListener('load', mungeData);
req.open('GET', 'data/EU-referendum-result-data.csv');
req.send();

This instantiates a new XMLHttpRequest object, tells it to load the data from the data/directory and then passes it to the soon-to-be-written mungeData() function once loaded.

Note how we had to use the ugly new keyword to instantiate it? Note how it took four lines and a new variable declaration? Note how we have to handle our response in a callback? Eww! We'll improve upon this in later chapters. The only advantage of doing things this way is that it works in nearly any browser without polyfilling, but there are so many better ways of doing this, all of which we will touch upon in Chapter 4, Making Data Useful.

The CSV file we're loading in has a row for each constituency in the UK, containing everything from what percentage voted for what to what the voter turnout was to how many ballots were invalid or spoiled. What we will do is turn that into an array of objects depicting the mean percentage for each broader region that voted for leaving.

It's time to create our mungeData() function. We will use d3.csvParse() (from the d3-dsv microlib) to parse our CSV data string in an object and then use some features from the d3-array microlib to manipulate that data:

function mungeData() { 
const data = d3.csvParse(this.responseText);
const regions = data.reduce((last, row) => {
if (!last[row.Region]) last[row.Region] = [];
last[row.Region].push(row);
return last;
}, {});
const regionsPctTurnout = Object.entries(regions)
.map(([region, areas]) => ({
region,
meanPctTurnout: d3.mean(areas, d => d.Pct_Turnout),
}));

renderChart(regionsPctTurnout);
}

Hey, there's another ES2015 feature! Instead of typing function() {} endlessly, you can now just put () => {} for anonymous functions. Other than being six keystrokes less, the fat arrow doesn't bind the value of this to something else. This won't impact us very much because we're using a functional style of programming; but if we were using classes, this would be a lifesaver. For more on this, visit http://mdn.io/Arrow_functions.

We transform our data in three steps here:

  1. First, we convert it into an array of objects using d3.csvParse() and assign the result to data.
  2. Then, we transform the array into an object keyed by the region, such that the object's keys are the regions, and the values are an array of associated constituencies.
  3. Lastly, Object.entries converts an object into a multidimensional array consisting of elements comprising key-value pairs, which we can then reduce into a new object comprising each region's name and the mean of each constituency's voter turnout percentage.

You may have noted that the function signature for the call to Array.prototype.map is a little unusual:

.map(([region, areas]) => { 

Here, we use a new ES2015 feature called destructuring assignment to give each element in our array a temporary name. Normally, the callback signature is the following:

function(item, index, array) {} 

However, because we know item is an array with two elements, we can give each of them a nickname, making our code easier to read (we don't use the index or array arguments this particular time, but if we did, we'd just put those arguments after the destructuring bit).

Lastly, we pass our fully munged data to an as-of-yet-unwritten function, renderChart(), which we'll add next.

We can also simply add the above to this:

  const regionsPctTurnout = d3.nest() 
.key(d => d.Region)
.rollup(d => d3.mean(d, leaf => leaf.Pct_Turnout))
.entries(data);

d3.nest() is part of the d3-collection microlib, which we'll cover in--you guessed it--Chapter 4, Making Data Useful. D3 is a very un-opinionated library, which means you can accomplish many tasks in a variety of ways--there often really isn't a proper way of doing things. I will try to expose a variety of ways to accomplish tasks throughout the book; feel free to choose whichever you prefer.

主站蜘蛛池模板: 同江市| 五常市| 古丈县| 饶阳县| 惠安县| 成武县| 华蓥市| 自贡市| 个旧市| 宜君县| 琼海市| 泸溪县| 吉水县| 福清市| 边坝县| 河南省| 尚志市| 左权县| 游戏| 广安市| 海口市| 二连浩特市| 交口县| 昌宁县| 嘉祥县| 霍林郭勒市| 广南县| 绥芬河市| 伊宁县| 长白| 巴东县| 多伦县| 崇阳县| 雷山县| 无极县| 佳木斯市| 高州市| 南华县| 新竹市| 上杭县| 汨罗市|