Build a Map of Eviction in San Francisco with CartoDB.js
Throughout this semester, through all of the small victories and the frustrations and the beautiful journey of self-directed learning, I've always had one key goal at the front of my mind – make a map, exclusively through code, that I believe in. This has become a more and more difficult challenge for me as I've expanded my cartographic skills and interests into different realms and more complex politics. I have come to expect more of myself, both in terms of the design and the aesthetics of my maps as well as the epistemologies and methodologies that underlie them. I don't know if I would necessarily go so far as to call all of my maps "lies" (as Monmonier might), but, in practicing self-reflexivity in my cartographic design process, I have learned that they are certainly far from being objective "truth". Maps reflect their creators' perspectives and views of the world; not only that, they channel particular ways of viewing, seeing, engaging with, and understanding the world that are dependent on the tools used to make them. That will always be the map's limitation. But rather than seeing maps only for their limitations, for their role as imperfect representations of a world that is inherently messy and complex, perhaps we can think of them differently – as individual experiences and expressions that can have meaning for others beyond the cartographer. Pieces of art that can inspire. Beautiful data that can inform. Little worlds unto themselves.
This philosophy influenced how I designed this map of eviction in San Francisco. When I was out in the Bay for AAG, I found myself often interested in exploring the geographies of the city even more than those I addressed at the conference. Having the chance to walk through the Mission, the Castro, the Sunset, the Richmond, to look and observe and understand so little (but feel so much) about those places, to get a momentary picture of a city undergoing fundamental and violent change – it forced me to think deeply and critically about my own experiences living in cities, and my own participation in gentrification and forced displacement. My own complicity. For this reason, I wanted to try to reckon with this part of my history and my identity through the crafts that I love – cartography and code.
Fortunately, the city of San Francisco has a pretty good resource for understanding demographic and social change within its boundaries – SF OpenData. From here, I was able to find a dataset listing every eviction notice filed between January 1, 1997 and December 31, 2015 in the city of San Francisco. Now, it is important to note here that 1) an eviction notice does not necessarily mean that an eviction occurred, and 2) that not all evictions that occur have legal eviction notices filed for them. Hence, the data visualized in this map is an incomplete picture, one that both adds and takes away; however, it does at least give us a strong starting point for understanding how eviction has moved and shifted across the city over the past 19 years. I also used SF OpenData to grab the neighborhood polygons as a KML file. The data on median house value and demographics comes from the American Community Surveys (2005-2009) and the 2010 Census, reaggregated by the San Francisco Planning Department to fit the boundaries of the neighborhoods (we could've used our nifty AWR tool to do that as well).
So that's a fair bit of data to be dealing with and trying to render on the fly on an interactive map. Due to this requirement on the project, I felt strongly that I needed to use a service that would allow me to create and host a spatial database without having to build and host one from scratch on my own machine. So, instead of going through Leaflet and using GeoJSON data (like Joe and I did for the Zuni map), I decided to use CartoDB. CartoDB offers users a PostGIS backend for creating spatial databases, all of which can be altered and queried using PostgreSQL commands. In this sense, CartoDB essentially acts as a database in the cloud, communicating with an interactive map somewhere else on the internet through use of its APIs. This makes life quite a bit easier, especially for those of us with elementary database design skills.
Click here to access the HTML used to make this map. A lot of things are happening in this map, so I won't go over absolutely everything. Instead, I'm going to focus on the parts that I think are cool or interesting and that may be helpful for future developers. So here we go.
You'll see early on in the code that we have a bunch of
<style> tags, many of which have bizarre-looking CSS inside them for different visualization types. These are actually written in CartoCSS, a DSL (domain-specific language) specifically for styling CartoDB web maps. The reason these are included here is that we have a function later in our code, called
createSelector, that does some pretty nifty stuff. First, there are event listeners tied to the various buttons on the map (i.e. All Ellis Act Eviction Notices, the Timelapse Map, the Heat Map, etc.), such that when one of these buttons is clicked, the
createSelector function is run on that visualization. The function itself actually reaches into the HTML of the selected visualization, finds the CartoCSS attached to that (all that stuff stuck between the
<style> tags), applies that CartoCSS to the data, and then adds it to the map. It's a complicated and multi-tiered process, but one that is really useful for applying many different styles to data with a relatively small amount of code.
Another cool element of this map is the custom HTML I wrote for the infowindows and the legends. The infowindows appear when you click on a neighborhood within the "Eviction Notices by Neighborhood" layer. The HTML I wrote for these little guys adds a nice black background to the neighborhood name, and then gives some information about the total number of eviction notices in the neighborhood since 1997, the median home value in 2010, and the racial makeup of the neighborhood in 2010. These are written using mustache templates, which have the benefit of allowing you to pull values from your PostGIS table into the HTML directly. Sweet! You'll also notice that two layers – the neighborhood layer and the heat map layer – have custom legends associated with them. I wired these legends to click events such that they only appear when the layer they describe is active – otherwise, they are turned off. Building custom legends is surprisingly easy; Daniel does a great job explaining how to do it in the blog post linked above. Again, it mostly involves writing some special HTML and CSS and getting your code to reach in there when a certain button is clicked. The powerful part of this functionality is that it really allows you to control the design of your map in a whole new way, such that you're not stuck with the limited options CartoDB gives you by default.
Lighter, which creates a brighter shade of blue for locations where eviction notices overlap. On a dark background like mine (designed by the highly-talented folks at Mapbox), this effectively draws the map reader's attention towards these areas on the map, allowing them to pick out areas of particularly aggressive displacement.
Ultimately, I feel satisfied with how this map turned out. As someone who is obsessed with details, with color, type, flow, kerning, tracking, visual hierarchy, and data legibility, I think I will always find something to critique about this map. But the time has come for me to move on from it as my last days at Middlebury come to a close. I don't doubt that I will continue to tweak it somewhere down the line, to add or take away or rework, but in this moment I feel a sense of peace with it. It feels like a map I can start to believe in, even if it doesn't feel completely done. And perhaps, at the end of all of this, it's as much of a symbol for me as an object in the world for others to learn from. A symbol that I can teach myself some pretty complicated things and come out with something on the other side. A symbol that I can use my skills to work for social justice, for marginalized voices, for stories that are not told. A symbol that my positionality will always place me in difficult political circumstances around the maps I make, in positions of power where I ought not to have it. Because, really, who am I to make these maps? What stake or experience do I have in these communities? What right do I have to tell these stories? These are questions I have not yet answered, and they are questions that require and demand answering. But I think these questions are also the starting places for critical cartographers. We start by engaging with those very things that challenge and frighten and discomfort us most. We start by attempting to do good while also mucking things up, and we learn from that. We start by using what we know to help others make sense of the world, messy and complicated and contradictory as it is. We start by making maps that we believe in.
Special thanks again to Professor Joseph Holler, Middlebury College Department of Geography, for his unwavering support of this senior research. Thanks are in order as well for Professors Kacy McKinney and Jeff Howarth, the two people who inspired my love for geography and cartography nearly four years ago. And, of course, to my parents, Chris and John, for believing in this kid and all of his wacky dreams, and for always showing me the way.
Thank you for reading. Stay posted for future reflections on my upcoming adventures as a Summer of Maps fellow at Azavea!