32  Location Choice

Code
import collections.abc

# hacky but necessary until a new pylogit is out
collections.Iterable = collections.abc.Iterable
from zipfile import ZipFile

import choicemodels
import geopandas as gpd
import numpy as np
import pandas as pd
import pylogit
import requests
import contextily as ctx
from geosnap import DataStore
from geosnap import io as gio
import matplotlib.pyplot as plt
OMP: Info #276: omp_set_nested routine deprecated, please use omp_set_max_active_levels instead.

Discrete choice modeling is central to modern urban analytics, but it is generally only taught in specific transportation subdisciplines. Since its inception, however, the discrete choice model has been viewed as a potentially superior method for understanding demand for housing attributes (Ellickson, 1981). If you want to be good at urban choice modeling, go study with civil engineers and transportation modelers. The field’s extensive history begins with McFadden & Reid (1975) and extends from there (Anas, 1980, 1981, 1983, 1984, 1985; Ben-Akiva & Bierlaire, 1999; Bhat, 1997; Bhat & Guo, 2004, 2007; Bhat & Koppelman, 2006; Donnelly et al., 2010; Guo & Bhat, 2007; Koppelman & Bhat, 2006; McFadden, 1978; McFadden & Train, 2000; Páez & Boisjoly, 2022; Pinjari et al., 2007; Rajamani et al., 2003). See also Jeffrey Newman’s transportation modeling course, or Michael Clark’s Categorical Regression Models course. The classic (and open) textbook is Train (2001), and Hensher et al. (2015) is a great, accessible, modern textbook.

Transportation modeling is a huge field, partly because it is well-funded by the federal government. Although integrated land-use/transportation models are part of the DNA of urban studies and regional science, land-use models (especially residential location-choice models) have received less attention (which is not to say the field is underdeveloped) (Batty, 1972; Benenson, 2004; Harris, 1985, 1994; Harris & Batty, 1993; Kain, 1987; Pagliara et al., 2010; Pinjari et al., 2007). Location-choice land-use models take a different form than the CA land-use models we explored in Chapter 26 because in the former we try to explicitly model demand from a behavioral perspective, rather than treat observations as automata.

“Simulation models of residential location meet several of our criteria for good models, failing partially on the question of behavioral realism, and most seriously with respect to social and ethnic externalities. Their theoretical and economic content is well-conceived, and they have begun to accommodate discrete choice behavior. The marriage between social science theory and simulation is not yet as secure as might be desired, and on many fronts much work remains to be done.

Harris (1985)

A residential location choice model is similar to a destination choice model in transportation research because there are dozens–maybe thousands of options in the choice set (unlike, say, a mode-choice model where there are only a handful of alternatives)

The crucial difference between location choice models and for example mode or destination choice models is that each of the alternatives is actually chosen by some household (in equilibrium). This is a significant difference from, say, mode choice models, where we are able to include alternatives chosen by nobody by generating them from travel supply data. In fact, were it not for differences across households such as income and family characteristics, the observable part of the utility ui would be the same for all residences, assuming market equilibrium prices. Generalized travel costs and environmental characteristics will be capitalized into housing prices. Thus, it is evident that the explaining power of the model is largely determined by how finely described the households are, as opposed to, say, mode choice models, where the travel time and travel cost of an alternative is often able to explain the observed choices to a large extent.

Eliasson (2010)

Notwithstanding the name, we generally view the parameters of a location ‘choice’ model as sorting influences rather than strict preferences (Quillian, 2015).

One important lesson from the last half-century of large-scale modeling exercises in the U.S. is that you cannot use models based on AI and ML to conduct scenario analysis for practical planning purposes (Lee, 1973; Spiekermann & Wegener, 2018). This modeling framework (e.g. the kind setup in Chapter 26) is interesting for exploration but impractical for policy development because (1) they are inaccurate and (2) the public distrusts them. In the first place, these models are not built on behavioral assumptions, so they do not accurately predict behavior in the future when scenario inputs are changed and simulated forward. In most cases, you need a structural modeling approach that assumes agents behave according to some behavioral principle (like utility maximization)–which is why McFadden (1978) won the Nobel prize (Manski, 2001). The discrete choice model famously provided far superior out-of-sample predictions for BART ridership than the prior generation of predictive models because it turns out to be a pretty accurate structural model of social behavior that is well-suited for policy analysis (Heckman & Vytlacil, 2007a; Heckman & Vytlacil, 2007b; Koopmans, 1949; Pearl, 1998)

Following, the best urban models rely on structural estimation (Holmes & Sieg, 2015) and require very thorough subject knowledge; this is essentially the antithesis of AI1. Second, urban planners have long rejected governance via computer overlord. Thus the point of modern scenario planning exercises is not only to develop simulated predictions under different growth assumptions, but also to communicate those findings to a constituency of residents and policymakers (Hopkins, 2014; Hopkins, 1974; Hopkins & Knaap, 2019; Hopkins & Zapata, 2007; Kaza & Hopkins, 2012; Klosterman, 1994; Knaap et al., 2020; Knaap et al., 1998; Spiekermann & Wegener, 2018). Good luck explaining that Deep Net (and soliciting buy-in) at your next planning commission meeting.

Metropolitan Planning Agencies needed models to assess the consequences of alternative transportation plans and policies on urban development and travel patterns. Some wanted to evaluate the effects of land policies such as the use of urban growth boundaries, or policies to promote transit-oriented development. Most wanted to be able to address these kinds of policy analysis questions with models that were behaviorally clear and as transparent as possible, avoiding the problems identified three decades ago by Lee’s critical assessment of the state of large scale urban simulation (Lee 1973), and the more general skepticism of “black-box” models that were so complex that their logic could not be explained to policy-makers or the public.

Waddell (2010)

In an integrated land-use/transportation (LU-TR) model (which is a stack of structural models…2), there is a repetitive iteration between location choices and transportation choices (Waddell, 2000, 2002; Wegener, 1994, 2004, 2021; Wegener, 1998). During each phase, the population chooses where to live and work. Then they choose how to commute and which route to take to work, which induces traffic congestion in the roadways. The congestion changes travel times, commuting speeds, and the level of accessibility at each location, so in the next round agents making location choices respond to this new layout (partially determined by choices other agents made). This yields a new spatial layout and a new set of transportation choices, etc., and this perpetual feedback loop allows land-use patterns and transport congestion to both be endogenous simulating into the future (de Palma et al., 2007)3.

In the 1950s first efforts were made in the USA to study the interrelationship between transport and the spatial development of cities systematically. Hansen (1959) demonstrated for Washington, DC that locations with good accessibility had a higher chance of being developed, and at a higher density, than remote locations (“How accessibility shapes land use”). The recognition that trip and location decisions co-determine each other and that therefore transport and land use planning needed to be co-ordinated, quickly spread among American planners, and the ‘land-use transport feedback cycle’ became a commonplace in the American planning literature. The set of relationships implied by this term can be briefly summarised as follows

Wegener (2004)‘s ’Land-Use Transportation Feedback Cycle’

Wegener (2004)‘s ’Land-Use Transportation Feedback Cycle’
  • The distribution of land uses, such as residential, industrial or commercial, over the urban area determines the locations of human activities such as living, working, shopping, education or leisure. - The distribution of human activities in space requires spatial interactions or trips in the transport system to overcome the distance between the locations of activities.
  • The distribution of infrastructure in the transport system creates opportunities for spatial interactions and can be measured as accessibility. - The distribution of accessibility in space co-determines location decisions and so results in changes of the land use system.

Wegener (2004)

In this framework, you can modify many public policies, e.g. constraining land supply to discourage sprawl, adding a new toll lane to decrease congestion, or increasing a transit fare to raise revenue, and the modeling system predicts how people’s behavior adapts to the new (partial) equilibrium. There are two major benefits to this approach: first, at the micro-level, (and at each decision step) agents are represented by a series of behavioral models that should perform well out-of-sample, and second, the constant endogeneity allows for unexpected complexity and emergence patterns. A simulation based on parameters estimated from a residential location-choice model is just a Schelling model with more complicated (and realistic) equation that governs each agent’s behavior, and can yield similar emergence patterns (Benenson, 1998, 2004; Hatna & Benenson, 2012)

32.1 Location as a Discrete Choice

Location-choice models are called many different things in the literature. Conceptually, our model assumes the role of [a class of] choosers (people) selecting from a huge set of alternatives (locations). Thus there are many discrete outcomes and our goal is to determine the probability of selecting each potential location. Generically, this model is called a multinomial logit model–which is often its name in the location choice and travel demand literature. Some researchers, however, prefer to call this approach the conditional logit (which is technically more accurate). In practice, it is common to see both.

The germane question for choosing a model becomes: is the chosen outcome a function of the chooser’s characteristics, or the alternative’s characteristics? (or both?). If we explain the choice as a function of the chooser, the model is preferably termed a multinomial logit, whereas if we explain the choice as a function of the differences between alternatives, the preferred term is a conditional logit. Apart from different data structures, these two models have slightly different interpretations, as Hoffman & Duncan (1988) describe. In particular, the conditional logit model is attractive for social science research because it maps onto a behavioral model of utility maximization.

This framework is called “random utility”, and it assumes people choose one alternative from a large set that maximizes their satisfaction. We cannot observe the value inherent in each alternative, so utilty is treated as a latent variable with a structural component and a random component (error). If we assume that the error associated with making the “best” choice follows an extreme-value distribution, we can estimate this model using an extension of the conventional binary logit. As a result, the model estimates the probability that each alternative will be chosen according to the value its combination of attributes provides to the choosers.

32.1.1 Multinomial and Conditional Logit

The formal specification of the choice model depends on whether we consider only attributes of the alternatives (i.e. the conditional logit model) or whether we also allow different groups of choosers (sometimes called “location consumers” in this context) to make different choices. The latter ability is a powerful feature of the conditional logit approach that separates it from other choice models (Schmidheiny & Brülhart, 2011). The issue is we have two (potentially interacting sets: choosers \(n\) and alternatives \(i\), both of which have a set of measurable attributes, usually denoted as \(X_n\) for the chooser characteristics and \(Z_i\) for the alternatives (location characteristics, in this case).

If we assume “utility” is the same for all consumers, then we only need to care about \(Z_i\) (i.e. only the characteristics of alternatives enter the model). If we assume that attributes of the chooser affect the chosen outcome, for example if taste is stratified by age, with younger consumers preferring downtown locations and older consumers preferring suburban locations, then we include interactions between these characteristics that allow for this flexibility \(X_n Z_i\). Thus in the fully-specified model, we have that utility \(U\) provided by unit \(i\) for household \(n\) is a function of structured value, \(V_{ni}\), provided by choice \(i\) for consumer \(n\), and extreme value (Gumbel) error

\[U = V_{ni} + \epsilon\].

The structured value component \(V_{ni}\) is linear-in-parameters of the form

\[V_{ni} =\alpha Z_i + \beta X_{n}Z_{i}\]

with \(Z_i\) as a vector of location attractiveness measures (population density, access to amenities, local public goods–education, air/water quality, etc.) and \(X_{n}Z_{i}\) as a vector of interaction terms of socio-demographic characteristics of chooser \(n\) with the attractiveness measures of location \(i\). Assuming that \(\epsilon\) follows an extreme-value distribution, the probability \(P\) of consumer \(n\) choosing location \(i\), is given by the conditional logit model (Guo & Bhat, 2004).

\[P_{ni} = \frac{e^{V_{ni}}}{\sum_{i}e^{V_{ni}}}\]

32.2 Where do Developers Use Low Income Housing Tax Credits (LIHTC)?

The allocation of affordable housing–especially subsidized housing–remains a crucial topic in public policy. A large body of work both past and present examines the ways that locations of subsidized housing stock, such as the Low Income Housing Tax Credit program (the largest affordable housing program in the U.S.) provides access to opportunity for low-income residents (Ahrentzen et al., 2023; McClure & Schwartz, 2023; Owens & Smith, 2023; Schwartz & McClure, 2023). The literature makes clear we should expect nuance in the distribution of LIHTC units; states differ in their “Qualified Allocation Plans” which determine how different locations are prioritized and incentivized for development, and different housing developers target different residents (e.g. elderly, or families with children) and it is natural to expect that “opportunity” may look different for these diverse populations (Knaap, 2017)

32.2.1 Data

To model LIHTC location sorting we will use the choicemodels library, distributed as part of the Urban Data Science Toolkit (Brathwaite & Walker, 2018; Foti & Waddell, n.d.), which provides tools for both data-wrangling and model estimation. The first task is to ensure that the dataset is formatted properly in the long format, which choice-modelers often call “individual choice alternative” or “IDCA” format. We begin by collecting raw data from the U.S. Department of Housing and Urban Development (as well as Census and the EPA), then use some geoprocessing to assign each LIHTC development to its “choice” of neighborhood and carry out the estimation. We start with property-level information on LIHTC units from HUD

HUD’s LIHTC database contains information on 53,032 projects and 3.65 million housing units placed in service between 1987 and 2022. Data for properties placed in service in 2023 will be collected in the fall of 2024 and added to this database in the spring of 2025. The database includes project address, number of units and low-income units, number of bedrooms, year the credit was allocated, year the project was placed in service, whether the project was new construction or rehab, type of credit provided, and other sources of project financing. The database has been geocoded, enabling researchers to look at the geographical distribution and neighborhood characteristics of tax credit projects. It may also help show how incentives to locate projects in low-income areas and other underserved markets are working. With the continued support of the national LIHTC database, HUD hopes to enable researchers to learn more about the effects of the tax credit program.

The file we need is a CSV, which is one of four files stored inside a zip archive. We also need to provide the webserver with a ‘user agent’, so we need to pass additional details that make the request appear to originate from a web browser (this is not necessarily doing something sneaky, we just need to tell the server what our ‘agent’ is capable of handling, so we say we are ‘firefox-capable’). We can pass those headers to the requests library and download the zipfile onto our local machine, then we use the zipfile library to peek into the archive and read only the CSV file we need using pandas.

Code
zfilename = "lihtcpub.zip"
headers = {
    "Content-Type": "application/json",
    "User-Agent": "Mozilla/5.0 (platform; rv:gecko-version) Gecko/gecko-trail Firefox/firefox-version",
}
# download the zip file onto the local disk
z = requests.get("https://www.huduser.gov/lihtc/lihtcpub.zip", headers=headers)
with open(f"./{zfilename}", "wb") as f:
    f.write(z.content)
# read the CSV inside the zip archive without extracting
with ZipFile(f"{zfilename}") as z:
    with z.open("LIHTCPUB.csv") as zfile:
        lihtc = pd.read_csv(zfile, low_memory=False)
lihtc.head()
hud_id project proj_add proj_cty proj_st proj_zip state_id latitude longitude place1990 ... n_unitsr li_unitr metro dda qct nonprog nlm_reason nlm_spc datanote record_stat
0 AKA0000X034 YENLO PHASE I AND II 402-451 NORTH YENLO STREET WASILLA AK 99654 AK-99-99 61.583094 -149.437633 NaN ... 37.0 37.0 NaN NaN NaN NaN NaN NaN NaN X
1 AKA0000X035 LITTLE DIPPER (ACQ/REHAB) 1910 TURNER STREET FAIRBANKS AK 99701 AK-99-99 64.829858 -147.723667 NaN ... 52.0 52.0 NaN NaN NaN NaN NaN NaN NaN N
2 AKA19890010 PARK WEST APTS 2012 SANDVIK ST FAIRBANKS AK 99709 AK-89-00001 64.851646 -147.803418 1080.0 ... 83.0 81.0 1.0 2.0 2.0 NaN NaN NaN NaN X
3 AKA19900005 TYSON'S TERRACE 103 BURKHART DR SITKA AK 99835 AK-90-00001 57.048874 -135.303021 3040.0 ... 16.0 16.0 1.0 0.0 2.0 NaN NaN NaN NaN X
4 AKA19910005 NORTHWOOD APTS 190 PARKWOOD CIR SOLDOTNA AK 99669 AK-91-00001 60.489146 -151.073858 2810.0 ... 23.0 22.0 1.0 0.0 2.0 NaN NaN NaN NaN X

5 rows × 79 columns

We now have a dataframe where each row represents a LIHTC location. Since the data come pre-geocoded (and comes with latitude/longitude) attributes, we can convert our dataframe into a geodataframe easily. For ease of presentation, we can first filter down to the state of California.

Code
ca_lihtc = lihtc[lihtc.proj_st == "CA"]
ca_lihtc = gpd.GeoDataFrame(
    ca_lihtc,
    geometry=gpd.points_from_xy(ca_lihtc.longitude, ca_lihtc.latitude),
    crs=4326,
)
Code
ca_lihtc[['li_units', 'geometry']].explore("li_units", scheme="quantiles", tiles="CartoDB Positron")
Make this Notebook Trusted to load map: File -> Trust Notebook

One quick observation is that the dataset is not geocoded perfectly. There is one development in the Pacific Ocean (off the coast of Catalina Island) and another in the Salton Sea in Imperial County. Since each location offers a different number of low-income units, we can scale the size of the circle to represent the number of units, then overlay with another variable like income or toxic release exposure.

Code
datasets = DataStore()
la_msa = gio.get_acs(datasets, msa_fips="31080", years=2015)
la_crs = la_msa.estimate_utm_crs()
la_msa = la_msa.to_crs(la_crs)

la_lihtc = ca_lihtc[ca_lihtc.to_crs(la_crs).intersects(la_msa.union_all())].to_crs(
    la_crs
)

gio.store_ejscreen(years=2017)
epa_tri = datasets.ejscreen(year=2017)
epa_tri = epa_tri.to_crs(la_crs)
epa_tri = epa_tri[epa_tri.geoid.isin(la_msa.geoid)]
Loading manifest:   0%|          | 0/12 [00:00<?, ?/s]Loading manifest: 100%|██████████| 12/12 [00:00<00:00, 24.4k/s]
  0%|          | 0.00/962M [00:00<?, ?B/s]  0%|          | 262k/962M [00:00<45:21, 353kB/s]  0%|          | 1.57M/962M [00:00<06:38, 2.41MB/s]  1%|          | 6.55M/962M [00:00<01:24, 11.3MB/s]  1%|          | 11.8M/962M [00:01<00:47, 19.8MB/s]  2%|▏         | 16.8M/962M [00:01<00:35, 26.7MB/s]  3%|▎         | 26.2M/962M [00:01<00:22, 41.8MB/s]  3%|▎         | 31.7M/962M [00:01<00:22, 41.8MB/s]  4%|▍         | 39.3M/962M [00:01<00:18, 49.0MB/s]  5%|▍         | 45.1M/962M [00:01<00:18, 49.3MB/s]  5%|▌         | 51.9M/962M [00:01<00:17, 53.0MB/s]  6%|▌         | 57.7M/962M [00:01<00:17, 51.5MB/s]  7%|▋         | 63.2M/962M [00:02<00:20, 43.2MB/s]  7%|▋         | 68.4M/962M [00:02<00:19, 45.2MB/s]  8%|▊         | 73.7M/962M [00:02<00:19, 46.2MB/s]  8%|▊         | 79.4M/962M [00:02<00:17, 49.2MB/s]  9%|▉         | 84.7M/962M [00:02<00:18, 48.4MB/s]  9%|▉         | 89.7M/962M [00:02<00:19, 44.7MB/s] 10%|▉         | 95.2M/962M [00:02<00:19, 45.6MB/s] 10%|█         | 99.9M/962M [00:02<00:18, 45.9MB/s] 11%|█         | 105M/962M [00:02<00:19, 44.6MB/s]  11%|█▏        | 110M/962M [00:03<00:18, 45.8MB/s] 12%|█▏        | 115M/962M [00:03<00:21, 39.9MB/s] 12%|█▏        | 119M/962M [00:03<00:21, 39.5MB/s] 13%|█▎        | 123M/962M [00:03<00:21, 38.5MB/s] 13%|█▎        | 128M/962M [00:03<00:20, 40.7MB/s] 14%|█▎        | 132M/962M [00:03<00:20, 40.8MB/s] 14%|█▍        | 136M/962M [00:03<00:21, 37.7MB/s] 15%|█▍        | 140M/962M [00:03<00:23, 35.4MB/s] 15%|█▍        | 144M/962M [00:03<00:23, 35.0MB/s] 15%|█▌        | 148M/962M [00:04<00:23, 34.7MB/s] 16%|█▌        | 152M/962M [00:04<00:22, 35.6MB/s] 16%|█▌        | 155M/962M [00:04<00:25, 31.5MB/s] 17%|█▋        | 159M/962M [00:04<00:28, 28.1MB/s] 17%|█▋        | 163M/962M [00:04<00:26, 30.5MB/s] 17%|█▋        | 166M/962M [00:04<00:28, 28.3MB/s] 18%|█▊        | 170M/962M [00:04<00:25, 30.9MB/s] 18%|█▊        | 174M/962M [00:04<00:26, 30.0MB/s] 18%|█▊        | 177M/962M [00:05<00:26, 29.8MB/s] 19%|█▊        | 180M/962M [00:05<00:26, 29.1MB/s] 19%|█▉        | 183M/962M [00:05<00:27, 27.8MB/s] 19%|█▉        | 187M/962M [00:05<00:27, 28.6MB/s] 20%|█▉        | 192M/962M [00:05<00:26, 28.6MB/s] 20%|██        | 195M/962M [00:05<00:29, 26.3MB/s] 21%|██        | 198M/962M [00:05<00:29, 26.1MB/s] 21%|██        | 200M/962M [00:06<00:30, 24.9MB/s] 21%|██        | 203M/962M [00:06<00:39, 19.2MB/s] 21%|██▏       | 206M/962M [00:06<00:35, 21.3MB/s] 22%|██▏       | 209M/962M [00:06<00:32, 23.4MB/s] 22%|██▏       | 212M/962M [00:06<00:29, 25.1MB/s] 22%|██▏       | 216M/962M [00:06<00:26, 28.3MB/s] 23%|██▎       | 219M/962M [00:06<00:26, 28.4MB/s] 23%|██▎       | 223M/962M [00:06<00:24, 29.8MB/s] 24%|██▎       | 226M/962M [00:07<00:25, 28.3MB/s] 24%|██▍       | 229M/962M [00:07<00:26, 27.6MB/s] 24%|██▍       | 233M/962M [00:07<00:24, 29.9MB/s] 25%|██▍       | 236M/962M [00:07<00:24, 29.9MB/s] 25%|██▍       | 240M/962M [00:07<00:23, 30.5MB/s] 25%|██▌       | 244M/962M [00:07<00:23, 30.6MB/s] 26%|██▌       | 247M/962M [00:07<00:22, 31.5MB/s] 26%|██▌       | 251M/962M [00:07<00:22, 31.2MB/s] 27%|██▋       | 256M/962M [00:07<00:20, 34.3MB/s] 27%|██▋       | 260M/962M [00:08<00:20, 34.3MB/s] 27%|██▋       | 263M/962M [00:08<00:22, 30.8MB/s] 28%|██▊       | 267M/962M [00:08<00:23, 29.6MB/s] 28%|██▊       | 271M/962M [00:08<00:20, 33.7MB/s] 29%|██▊       | 275M/962M [00:08<00:22, 31.1MB/s] 29%|██▉       | 279M/962M [00:08<00:21, 31.0MB/s] 29%|██▉       | 283M/962M [00:08<00:22, 30.0MB/s] 30%|██▉       | 287M/962M [00:08<00:22, 29.4MB/s] 30%|███       | 290M/962M [00:09<00:21, 31.8MB/s] 31%|███       | 295M/962M [00:09<00:19, 34.0MB/s] 31%|███       | 299M/962M [00:09<00:18, 35.9MB/s] 31%|███▏      | 303M/962M [00:09<00:19, 33.4MB/s] 32%|███▏      | 306M/962M [00:09<00:19, 32.8MB/s] 32%|███▏      | 310M/962M [00:09<00:21, 30.5MB/s] 33%|███▎      | 313M/962M [00:09<00:20, 31.6MB/s] 33%|███▎      | 317M/962M [00:09<00:19, 33.1MB/s] 33%|███▎      | 322M/962M [00:09<00:18, 35.3MB/s] 34%|███▍      | 326M/962M [00:10<00:17, 35.5MB/s] 34%|███▍      | 330M/962M [00:10<00:18, 34.6MB/s] 35%|███▍      | 333M/962M [00:10<00:18, 34.8MB/s] 35%|███▌      | 337M/962M [00:10<00:18, 33.5MB/s] 35%|███▌      | 341M/962M [00:10<00:18, 34.0MB/s] 36%|███▌      | 345M/962M [00:10<00:17, 36.1MB/s] 36%|███▌      | 348M/962M [00:10<00:17, 34.9MB/s] 37%|███▋      | 352M/962M [00:10<00:18, 33.7MB/s] 37%|███▋      | 356M/962M [00:10<00:17, 33.9MB/s] 38%|███▊      | 361M/962M [00:11<00:15, 37.7MB/s] 38%|███▊      | 365M/962M [00:11<00:15, 38.1MB/s] 38%|███▊      | 369M/962M [00:11<00:16, 36.8MB/s] 39%|███▉      | 373M/962M [00:11<00:15, 37.2MB/s] 39%|███▉      | 377M/962M [00:11<00:16, 36.2MB/s] 40%|███▉      | 382M/962M [00:11<00:14, 38.9MB/s] 40%|████      | 386M/962M [00:11<00:15, 38.2MB/s] 41%|████      | 390M/962M [00:11<00:15, 37.5MB/s] 41%|████      | 394M/962M [00:11<00:16, 34.2MB/s] 41%|████▏     | 398M/962M [00:12<00:16, 34.4MB/s] 42%|████▏     | 402M/962M [00:12<00:15, 37.0MB/s] 42%|████▏     | 407M/962M [00:12<00:14, 39.0MB/s] 43%|████▎     | 412M/962M [00:12<00:14, 39.1MB/s] 43%|████▎     | 416M/962M [00:12<00:13, 39.2MB/s] 44%|████▎     | 420M/962M [00:12<00:14, 37.5MB/s] 44%|████▍     | 424M/962M [00:12<00:14, 37.1MB/s] 45%|████▍     | 428M/962M [00:12<00:13, 38.9MB/s] 45%|████▍     | 432M/962M [00:12<00:13, 38.9MB/s] 45%|████▌     | 436M/962M [00:13<00:13, 38.0MB/s] 46%|████▌     | 440M/962M [00:13<00:13, 38.3MB/s] 46%|████▌     | 444M/962M [00:13<00:13, 38.2MB/s] 47%|████▋     | 448M/962M [00:13<00:14, 35.8MB/s] 47%|████▋     | 452M/962M [00:13<00:13, 38.2MB/s] 47%|████▋     | 456M/962M [00:13<00:15, 32.7MB/s] 48%|████▊     | 460M/962M [00:13<00:15, 32.4MB/s] 48%|████▊     | 464M/962M [00:13<00:14, 33.7MB/s] 49%|████▊     | 468M/962M [00:13<00:14, 34.5MB/s] 49%|████▉     | 471M/962M [00:14<00:14, 33.5MB/s] 49%|████▉     | 476M/962M [00:14<00:13, 35.9MB/s] 50%|████▉     | 480M/962M [00:14<00:13, 35.6MB/s] 50%|█████     | 483M/962M [00:14<00:13, 35.8MB/s] 51%|█████     | 488M/962M [00:14<00:13, 36.4MB/s] 51%|█████     | 493M/962M [00:14<00:11, 39.3MB/s] 52%|█████▏    | 497M/962M [00:14<00:12, 38.7MB/s] 52%|█████▏    | 501M/962M [00:14<00:11, 39.2MB/s] 53%|█████▎    | 505M/962M [00:14<00:12, 37.1MB/s] 53%|█████▎    | 510M/962M [00:15<00:11, 39.7MB/s] 53%|█████▎    | 514M/962M [00:15<00:12, 37.3MB/s] 54%|█████▍    | 519M/962M [00:15<00:11, 39.7MB/s] 54%|█████▍    | 523M/962M [00:15<00:11, 38.3MB/s] 55%|█████▍    | 527M/962M [00:15<00:11, 38.2MB/s] 55%|█████▌    | 532M/962M [00:15<00:10, 40.6MB/s] 56%|█████▌    | 537M/962M [00:15<00:10, 42.4MB/s] 56%|█████▋    | 541M/962M [00:15<00:09, 42.6MB/s] 57%|█████▋    | 546M/962M [00:15<00:09, 44.0MB/s] 57%|█████▋    | 551M/962M [00:16<00:09, 42.7MB/s] 58%|█████▊    | 555M/962M [00:16<00:09, 42.2MB/s] 58%|█████▊    | 560M/962M [00:16<00:10, 38.9MB/s] 59%|█████▊    | 564M/962M [00:16<00:10, 39.6MB/s] 59%|█████▉    | 568M/962M [00:16<00:09, 39.6MB/s] 60%|█████▉    | 573M/962M [00:16<00:09, 40.5MB/s] 60%|█████▉    | 577M/962M [00:16<00:11, 34.8MB/s] 61%|██████    | 582M/962M [00:16<00:09, 39.6MB/s] 61%|██████    | 586M/962M [00:17<00:09, 39.0MB/s] 61%|██████▏   | 591M/962M [00:17<00:09, 39.7MB/s] 62%|██████▏   | 595M/962M [00:17<00:08, 41.6MB/s] 62%|██████▏   | 600M/962M [00:17<00:09, 37.5MB/s] 63%|██████▎   | 604M/962M [00:17<00:10, 35.7MB/s] 63%|██████▎   | 607M/962M [00:17<00:10, 34.5MB/s] 64%|██████▎   | 611M/962M [00:17<00:11, 30.4MB/s] 64%|██████▍   | 615M/962M [00:17<00:11, 30.0MB/s] 64%|██████▍   | 619M/962M [00:17<00:10, 32.2MB/s] 65%|██████▍   | 622M/962M [00:18<00:11, 29.8MB/s] 65%|██████▌   | 625M/962M [00:18<00:11, 29.5MB/s] 65%|██████▌   | 629M/962M [00:18<00:10, 31.8MB/s] 66%|██████▌   | 633M/962M [00:18<00:10, 30.6MB/s] 66%|██████▌   | 636M/962M [00:18<00:10, 31.9MB/s] 67%|██████▋   | 640M/962M [00:18<00:09, 32.3MB/s] 67%|██████▋   | 644M/962M [00:18<00:08, 35.5MB/s] 67%|██████▋   | 648M/962M [00:18<00:09, 33.9MB/s] 68%|██████▊   | 652M/962M [00:18<00:08, 35.0MB/s] 68%|██████▊   | 656M/962M [00:19<00:08, 36.0MB/s] 69%|██████▊   | 660M/962M [00:19<00:08, 35.3MB/s] 69%|██████▉   | 663M/962M [00:19<00:09, 32.7MB/s] 69%|██████▉   | 667M/962M [00:19<00:09, 31.6MB/s] 70%|██████▉   | 671M/962M [00:19<00:09, 31.6MB/s] 70%|███████   | 676M/962M [00:19<00:08, 35.4MB/s] 71%|███████   | 679M/962M [00:19<00:08, 34.9MB/s] 71%|███████   | 684M/962M [00:19<00:07, 38.2MB/s] 72%|███████▏  | 688M/962M [00:20<00:07, 36.2MB/s] 72%|███████▏  | 693M/962M [00:20<00:06, 38.7MB/s] 73%|███████▎  | 698M/962M [00:20<00:06, 40.4MB/s] 73%|███████▎  | 702M/962M [00:20<00:06, 39.5MB/s] 73%|███████▎  | 706M/962M [00:20<00:06, 40.2MB/s] 74%|███████▍  | 712M/962M [00:20<00:05, 43.5MB/s] 74%|███████▍  | 716M/962M [00:20<00:06, 36.7MB/s] 75%|███████▍  | 720M/962M [00:20<00:06, 36.6MB/s] 75%|███████▌  | 724M/962M [00:20<00:06, 35.1MB/s] 76%|███████▌  | 728M/962M [00:21<00:06, 34.7MB/s] 76%|███████▌  | 732M/962M [00:21<00:06, 35.9MB/s] 77%|███████▋  | 737M/962M [00:21<00:05, 38.7MB/s] 77%|███████▋  | 741M/962M [00:21<00:05, 39.2MB/s] 78%|███████▊  | 746M/962M [00:21<00:05, 40.4MB/s] 78%|███████▊  | 750M/962M [00:21<00:05, 38.9MB/s] 78%|███████▊  | 754M/962M [00:21<00:05, 38.3MB/s] 79%|███████▉  | 759M/962M [00:21<00:05, 38.4MB/s] 79%|███████▉  | 763M/962M [00:21<00:04, 40.1MB/s] 80%|███████▉  | 768M/962M [00:22<00:04, 40.5MB/s] 80%|████████  | 772M/962M [00:22<00:04, 41.4MB/s] 81%|████████  | 777M/962M [00:22<00:04, 42.7MB/s] 81%|████████▏ | 781M/962M [00:22<00:04, 43.7MB/s] 82%|████████▏ | 786M/962M [00:22<00:04, 42.3MB/s] 82%|████████▏ | 791M/962M [00:22<00:03, 43.4MB/s] 83%|████████▎ | 795M/962M [00:22<00:04, 37.4MB/s] 83%|████████▎ | 799M/962M [00:22<00:04, 37.8MB/s] 83%|████████▎ | 803M/962M [00:22<00:04, 36.7MB/s] 84%|████████▍ | 808M/962M [00:23<00:03, 40.1MB/s] 84%|████████▍ | 812M/962M [00:23<00:04, 35.2MB/s] 85%|████████▍ | 816M/962M [00:23<00:04, 36.2MB/s] 85%|████████▌ | 821M/962M [00:23<00:03, 37.4MB/s] 86%|████████▌ | 826M/962M [00:23<00:03, 40.8MB/s] 86%|████████▋ | 831M/962M [00:23<00:03, 42.2MB/s] 87%|████████▋ | 835M/962M [00:23<00:02, 42.9MB/s] 87%|████████▋ | 840M/962M [00:23<00:02, 41.6MB/s] 88%|████████▊ | 845M/962M [00:24<00:03, 37.9MB/s] 88%|████████▊ | 849M/962M [00:24<00:02, 37.6MB/s] 89%|████████▊ | 854M/962M [00:24<00:02, 38.8MB/s] 89%|████████▉ | 859M/962M [00:24<00:02, 42.2MB/s] 90%|████████▉ | 863M/962M [00:24<00:02, 39.3MB/s] 90%|█████████ | 867M/962M [00:24<00:02, 39.3MB/s] 91%|█████████ | 872M/962M [00:24<00:02, 34.8MB/s] 91%|█████████ | 876M/962M [00:24<00:02, 35.5MB/s] 91%|█████████▏| 879M/962M [00:24<00:02, 35.1MB/s] 92%|█████████▏| 883M/962M [00:25<00:02, 34.7MB/s] 92%|█████████▏| 887M/962M [00:25<00:02, 36.3MB/s] 93%|█████████▎| 892M/962M [00:25<00:01, 35.8MB/s] 93%|█████████▎| 897M/962M [00:25<00:01, 39.8MB/s] 94%|█████████▎| 902M/962M [00:25<00:01, 39.0MB/s] 94%|█████████▍| 906M/962M [00:25<00:01, 40.3MB/s] 95%|█████████▍| 910M/962M [00:25<00:01, 38.9MB/s] 95%|█████████▌| 915M/962M [00:25<00:01, 40.2MB/s] 96%|█████████▌| 919M/962M [00:26<00:01, 33.7MB/s] 96%|█████████▌| 923M/962M [00:26<00:01, 34.7MB/s] 96%|█████████▋| 927M/962M [00:26<00:01, 34.2MB/s] 97%|█████████▋| 932M/962M [00:26<00:00, 35.6MB/s] 97%|█████████▋| 936M/962M [00:26<00:00, 29.9MB/s] 98%|█████████▊| 939M/962M [00:26<00:00, 27.6MB/s] 98%|█████████▊| 942M/962M [00:26<00:00, 26.1MB/s] 98%|█████████▊| 945M/962M [00:26<00:00, 26.5MB/s] 99%|█████████▊| 948M/962M [00:27<00:00, 17.1MB/s] 99%|█████████▉| 951M/962M [00:27<00:01, 11.2MB/s] 99%|█████████▉| 952M/962M [00:28<00:00, 9.53MB/s] 99%|█████████▉| 954M/962M [00:28<00:00, 8.51MB/s] 99%|█████████▉| 955M/962M [00:28<00:00, 7.58MB/s] 99%|█████████▉| 956M/962M [00:28<00:00, 7.55MB/s]100%|█████████▉| 957M/962M [00:28<00:00, 6.93MB/s]100%|█████████▉| 958M/962M [00:29<00:00, 5.65MB/s]100%|█████████▉| 959M/962M [00:29<00:00, 4.59MB/s]100%|█████████▉| 960M/962M [00:29<00:00, 4.12MB/s]100%|█████████▉| 960M/962M [00:29<00:00, 3.61MB/s]100%|█████████▉| 961M/962M [00:30<00:00, 2.42MB/s]100%|█████████▉| 961M/962M [00:30<00:00, 1.95MB/s]100%|█████████▉| 962M/962M [00:31<00:00, 1.83MB/s]100%|██████████| 962M/962M [00:31<00:00, 1.73MB/s]100%|██████████| 962M/962M [00:31<00:00, 30.7MB/s]
Code
m = (
    epa_tri[["RESP", "T_RESP", "geometry"]]
    .assign(geometry=epa_tri.geometry.simplify(10))
    .explore("RESP", scheme="quantiles", tiles="CartoDB Positron", tooltip="T_RESP", style_kwds={'weight':0.5})
)
la_lihtc[['li_units', 'geometry']].explore(
    m=m,
    color="red",
    style_kwds={
        "style_function": lambda x: {"radius": x["properties"]["li_units"] ** 0.5}
    },
    tooltip=False,
)
Make this Notebook Trusted to load map: File -> Trust Notebook