Tornadoes caused $25 billion dollars worth of damage to the US in 2011. Since 1953 NOAA has recorded 57,988 tornadoes that made landfall. Using Turf, let’s cross-reference this data with the Census Bureau’s county boundaries and visualize which of the country’s 3,221 counties have been hit hardest over the last fifty years.

At nearly 50MB of data, we will want to perform this analysis on a desktop or server, rather than in a browser. Turf runs in these environments using Node.js, a JavaScript server-side programming platform. Using Turf in this way, analysis can be performed and automated on massive datasets without worrying about bandwidth.

Let’s get started by cloning a repository that contains the GeoJSON data we will need.

git clone https://github.com/mapbox/tornado-analysis.git
cd tornado-analysis

Now we can install Turf using the Node.js package manager, npm.

npm install turf

Now open the included index.js file in your text editor. We will edit this file with the code below, and execute the code with the command:

node index.js

Load the turf and filesystem modules.

var fs = require('fs');
var turf = require('turf');

Read the counties into memory. The counties.json is a GeoJSON file that contains polygons for all counties in the US.

var counties = require('./counties.json');

Read the tornadoes into memory. The tornadoes.json is a GeoJSON file that contains lines for all tornado paths since 1950.

var tornadoes = require('./tornadoes.json');

Use turf.centroid to calculate the center point of every tornado.

var centroids = turf.featurecollection([]);
for(var i = 0; i < tornadoes.features.length; i++) {
  centroids.features.push(turf.centroid(tornadoes.features[i]));
}

Count all the tornadoes that fall within each county using turf.inside.

for(var i = 0; i < counties.features.length; i++) {
    counties.features[i].properties = {};
    counties.features[i].bbox = turf.extent(counties.features[i]);
    counties.features[i].properties.tornadoes = 0;
    for(var j = 0; j < centroids.features.length; j++) {
        // if the tornado is within the county's bbox, run turf.inside
        if(centroids.features[j].geometry.coordinates[0] >= counties.features[i].bbox[0] &&
           centroids.features[j].geometry.coordinates[0] <= counties.features[i].bbox[2] &&
           centroids.features[j].geometry.coordinates[1] >= counties.features[i].bbox[1] &&
           centroids.features[j].geometry.coordinates[1] <= counties.features[i].bbox[3] &&
           turf.inside(centroids.features[j],counties.features[i])) {
            counties.features[i].properties.tornadoes++;
        }
    }
}

The code above does not take county size into account. This will give too much weight to larger counties (especially in the Western US). Let’s calculate the area for each of the counties, then then divide the tornado count by this number to calculate tornado density. As expected, the results shift to the Midwest, and large counties in the Southwest move down in rank.

for(var i = 0; i < counties.features.length; i++) {
	counties.features[i].properties.area = (Math.round(turf.area(counties.features[i].geometry) * 0.000621371))/100000;
	counties.features[i].properties.tornado_density =
		counties.features[i].properties.tornadoes
		/ counties.features[i].properties.area;
}

Now we can write the results to a file where it can be opened and visualized in your cartography application of choice.

fs.writeFileSync('./result.geojson', JSON.stringify(counties));

Want to learn more? Check the Turf examples page, or reach out and let us know how you are using Turf with @Mapbox.