The past few years, I lead a tutorial for the UCSF Family and Community Medicine Residents where we created maps of ED visits in California related to asthma (slides available: here; asthma map available: here). It's very powerful to view this information on a map, rather than in a table, where it's nearly meaningless unless you have your zip codes memorized.

But what if we wanted to compare this information to another variable, say income. Do zip codes with higher median household income, in general, have higher rates of asthma? One way of doing this is to create two maps (one for income, one for asthma) and hold them side-by-side, comparing each zip code individually. But that doesn't let us quickly query our map or really explore our data in much depth.

Enter Crosslet.js, a powerful and fun Javascript library that combines three other useful libraries: D3, Leaflet, and Crossfilter. Crosslet lets us connect our map to multiple variables for each polygon (in this case being zip code) and query across all of them simultaneously.

Check out the example below. Use the filters on the top right to select higher household incomes. Then, drag the blue box to the left and watch the histogram for asthma visits. See how the histogram showing asthma visits shifts to the right as we select poorer zip codes? I also included the percent of the population that identified as Black or African American in the latest census. This lets us quickly view the relationship between race and income, race and asthma, or all three variables together. (Stay tuned for a tutorial on how to scrape this data from sites like ZipAtlas using a simple and powefful API-generating tool called Kimono).

This project maps crimes in San Francisco. You can filter the map by types of crime, district of SF, and date. Also, try clicking on the tab titled 'Graphs' to see summary graphs of:

Total crimes per day of week

Crimes by date

Crimes by time of dat

Crimes by type of crime

Try panning the map and notice how these graphs automatically update based on the crimes that are visible in the window. This feature makes it fast and easy to compare crimes from one neighborhood to another - all you have to do is pan the map and see how the graphs change!

I used the Forecast.io API to automatically generate a wind rose of anywhere in the world with one click! This will come in handy when I need to estimate pesticide exposures and exposure to traffic-related air pollution. Thanks Forecast for the free 1000 API calls per day - super generous! The overlay shows average wind speed.

We can use APIs like this to help us understand how wind speed and direction impact your health. My research shows how this data lets us research weather patterns and asthma inhaler use.

Last post, I talked about dot density maps as a way of taking polygons (like zip codes) and distributing their population evenly across the area in the form of dots. If 1000 people live in a zip code, then place 1000 random dots inside it. That's useful for visualizing population density, but what if you could then add these dots back together across new polygons? You'd be able to then get a pretty good estimate of the population within a new boundary.

For example, we can take the locations of clinics in Pretoria and create "Thessian" polygons (otherwise known as a Voronoi diagram) that show the area for which that particular clinic is closest. In other words, if you are in the Thessian polygon for Clinic A, then you are closer to Clinic A than to any other clinic. It's a rudimentary way of calculating a catchment area for each clinic. Then, we can overlay our population dot density map. Finally, we can just count the dots inside each clinic catchment to estimate the total population served by that clinic.

I'll include my R code below so you can replicate these results if you'd like. A sidenote on mapping in R: I never understood why people would map in R, when you could map in QGIS, Tilemill, Mapbox, Leaflet or other programs that seemed more intuitive. What I now recognize is that R keeps everything reproducible, which is essential for publishing. Also, it makes in incredibly easy to repeat your entire script with new data or variables. For example, we can rerun this same analysis for the entire country of South Africa with only a few extra lines of code!

Below is the R code. It is thoroughly commented but email me or write a comment if something doesn't make sense and I can update the Gist. The code is a bit long, but that's partly due to some data cleanup in the beginning, plus additional code for printing all four of the maps in the GIF above.

I'm working on building dot density maps of South Africa using census data. Below is an example of what I'm talking about. Each dot on the map shows 100 people living in Tshwane, the municipality in which I'm currently living. If you can then calculate "catchment" areas for each clinic (the simplest way is to use the shortest Euclidean distance by creating a Voronoi diagram), we will be able to estimate the total number of people served by each clinic. This information, combined with information we have about health outcomes and financial resources of each clinic, will help identify those clinics with the highest burden and fewest resources.

In researching these types of maps, I've seen other people create massive dot density maps that are color coded by ethnicity/race. Adrian Frith created a great dot map of South Africa. Below I've embedded a similar map made by the Cooper Center. I'm reminded of the Facebook connections map, in that you can clearly visualize the roads, boundaries and the topography of the entire US, even though the only thing that is mapped is dots - there are no lines in the entire map.

California SB 277 has passed the state Assembly. If it is approved by Jerry Brown, this will end the personal belief exemption (PBE) in California. The map below shows the location of all middle schools in California with at least one student who is unvaccinated due to a PBE. You can read more about how this map was made in the popup on the map, and can access a full-size version of the map here.