-
Notifications
You must be signed in to change notification settings - Fork 0
/
An Environmental Justice Analysis of Gas Leaks3.Rmd
3138 lines (2756 loc) · 210 KB
/
An Environmental Justice Analysis of Gas Leaks3.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
---
title: "An Environmental Justice Analysis of Distribution-Level Natural Gas Leaks in Massachusetts, USA"
author:
date:
output:
bookdown::pdf_document2:
latex_engine: xelatex
keep_tex: yes
toc: false
number_sections: true
fig_caption: yes
includes:
in_header: my_header.tex
link-citations: yes
bibliography: GasLeaksEJBIB.bib
csl: chicago-author-date.csl
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo=FALSE, message=FALSE, warning=FALSE)
```
**Authors:**
Marcos Luna[^a][^*] and Dominic Nicholas[^b]
[^a]: Geography and Sustainability Department, Salem State University, 352 Lafayette Street, Salem, Massachusetts, USA 01970. [email protected].
[^b]: HEET (Home Energy Efficiency Team), 21 Acorn Street, Cambridge, Massachusetts, USA 02139. [email protected].
[^*]: Corresponding author.
# Abstract {-}
A growing body of research shows that natural gas leaks at the distribution level are much more common and extensive than previously thought. Although scholars and advocates have raised alarms about the climate change and economic significance of these leaks, there has been little consideration of the problem from an environmental justice perspective. Using recently available high resolution leak data, this analysis of natural gas leaks across the state of Massachusetts shows that People of Color, limited English speaking households, and renters are disproportionately exposed to natural gas leaks, as compared to White residents and to homeowners. This pattern is evident for all leaks in the state, for leaks disaggregated by leak class or grade, and for leaks disaggregated by utility. This analysis shows that natural gas leaks are an environmental justice issue warranting further study and policy attention.
keywords: natural gas distribution, utilities, leaks, environmental justice, equity, race
\pagebreak
# Introduction
From the wellhead to the gas appliances in homes, researchers increasingly find that natural gas leaks are more common and extensive than previously understood or reported. These leaks have outsized climate impacts because methane, the primary constituent of natural gas, has more than 80 times the global warming potential of carbon dioxide over the first 20 years that it reaches the atmosphere. Lost methane may account for one quarter of current warming [@EDF2021]. Locally, gas leaks pose explosive fire hazards, contribute to degradation of indoor and outdoor air quality, and kill street trees. Moreover, the loss of natural gas represents an economic burden both to consumers and to distributors. Despite rapid growth in studies about the extent of gas leaks and methods to detect them, research on gas leaks from an equity perspective has been rare and inconclusive [@PHILLIPS20131; @Scott_Scott_2019]. As with many other forms of environmental and energy challenges, there is reason to suspect that the experience of natural gas leaks is neither equal nor equitable.
This paper assesses the degree to which distribution-level natural gas leaks are distributed inequitably and how repair of these leaks varies between communities across the state of Massachusetts, USA. To perform this assessment, we utilize newly available street-level records of gas leaks reported by natural gas utilities which have been geocoded by the Home Energy Efficiency Team (HEET). The gas leaks records reveal not only detailed information about individual leak locations, but also their first reporting date, whether or when they were repaired, and their leak class or grade (i.e., hazardousness). We compare the relative frequency of these leaks across communities at varying geographic scales using American Community Survey census data to determine whether there are systematic differences in exposure or timeliness of repair for different geographic communities and population subgroups.
This high resolution, statewide assessment of gas leaks exposure and response applies a much-needed environmental justice framework to the problem of natural gas leaks. It advances on prior work on gas leaks occurrence which has been limited to independent analyses of specific municipalities [@PHILLIPS20131], or which has been conducted at coarse geographic scales due to the lack of detailed data below regional or utility-scale reporting [@Scott_Scott_2019]. This analysis draws on a robust body of environmental justice research and practice to demonstrate the application of an equity analysis to the problem of distribution-level gas leaks. The results validate concerns that exposure and response to natural gas leaks are inequitable. These findings affirm the value to regulators, utilities, and communities of adopting an environmental justice perspective to reveal and understand how inequities are created and perpetuated in natural gas distribution. This study also highlights the critical importance of detailed and transparent reporting by utilities and their regulators to support environmental justice.
# Background
## Gas service provision in Massachusetts
Natural gas consumption in Massachusetts has grown dramatically in the last three decades – over 200% since the early 1980s – displacing coal, oil, and nuclear power for electricity generation, and wood and fuel oil for home heating [@EIA_2021]. At the end of 2019, approximately two-thirds of electricity generation in the state was fueled by natural gas, with the remainder made up primarily by hydroelectricity, biomass, and various sources of renewable energy [@EIA_2020]. However, households are the single largest consumers of natural gas, representing over 30% of total consumption for the state, most of which is used for hot water and space heating [@EIA_2015; @EIA_2019]. More than half (52%) of all residences in Massachusetts (1.4 million occupied housing units) rely on utility-supplied, piped natural gas as their primary source of home heating, with the remainder reliant primarily on fuel oil (24%) or electricity (17%) [@Census_2019].
Despite aggressive marketing by utilities and the natural gas trade association about the economic and environmental benefits of natural gas [@AGA2021; @Hall_2021; @Leber_2021], its appeal has been undermined by revelations about the extent of gas leaks, high profile disasters, and initiatives by the state and municipalities to dramatically and rapidly reduce greenhouse gas emissions [@Borunda2020; @Roberts_2019; @Volcovici2021].
## Crises of gas leakage
Leakage of natural gas from production through transportation and distribution has long been recognized, but a growing body of research has revealed that the extent of these losses is much greater than reported by the natural gas industry or estimated by regulators. Until 2009, the U.S. Environmental Protection Agency (EPA) relied on a joint EPA-industry assessment from 1996 that estimated about 1.4% of the methane in the natural gas system was lost to the atmosphere, with incremental revisions of upstream emissions estimates in subsequent years [@Howarth_2014]. However, researchers using independent systems of analyses, including life cycle assessment and atmospheric measurements, found that methane emissions from the natural gas system were likely at least two to three times greater than government and industry estimates [@Brandt_Heath_2014; @Howarth2011; @McKain2015; @Plant_Kort_2019; @Inman_Grubert_2020]. Until recently, however, there was very little research or reporting allowing for disaggregation of lost gas or methane emissions at the distribution level [@Weller_Hamburg_2020].
In Massachusetts, @PHILLIPS20131 pioneered a portable, street-level method of gas leak detection using a vehicle-mounted cavity ring-down spectrometer. The results and the maps they released beginning in 2012 showed that Boston was suffused by excessive levels of methane along the 785 miles of road they surveyed [@Daley_2012]. They argued that these concentrations could not be explained by natural sources and must be from leaks in gas mains buried beneath the streets. Their methods were replicated in municipalities across the country, from Washington D.C. [@Jackson_Down_2014] and New York City [@Gallagher_Down_2015] to Los Angeles [@Hopkins_Kort_2016]. These studies confirmed that gas leaks are a ubiquitous problem in the distribution system. Despite the growth in such studies, however, most have continued to focus on methodologies for the detection and quantification of methane from natural gas distribution, with virtually no attention to its environmental health or social implications [@vonFischer_2017; @Cho_Ulrich_2020; @Keyes_Ridge_2020; @Weller_2018].
With over 6,000 miles of aging, leak-prone infrastructure [@DPU_2019], Massachusetts bears a disproportionate share of the country’s leak-prone gas pipelines [@Herdes_Campbell_2020]. In 2009, the Massachusetts Department of Public Utilities (DPU) started approving plans for accelerated replacement of leak-prone infrastructure [@DPU_2019]. However, the pace of repair was frequently criticized [@Norton2011]. In 2013, Congress released a study commissioned by Massachusetts Senator Edward Markey showing that US natural gas customers had paid \$20 billion over a decade (2000 - 2011) for gas that they had never received; over $1.5 billion in Massachusetts alone [@House_2013]. Massachusetts subsequently passed legislation requiring utilities to submit annual plans to repair or replace leak-prone natural gas infrastructure, adopt a consistent system of leak hazard classification with timelines for monitoring and repair, and crucially (for this analysis), to submit publicly-accessible reports of the status and locations of leaks to the DPU [@GasLeakAct].
The first reports were filed with the DPU in 2015. HEET, a non-profit environmental advocacy organization based in Cambridge, Massachusetts, cleaned up and translated the data from these reports into accessible, online Google maps showing the location, grade, and status of the leaks for hundreds of communities across the state. They released these maps to the public beginning in summer 2015 [@Chakrabarti_2015]. HEET has continued this service annually with each release of the DPU data, performing quality control, and becoming the de facto source for publicly accessible maps of utility-reported leaks in Massachusetts (https://heet.org/). The sustained visibility of gas leaks has become an invaluable resource for advocates to hold utilities, the DPU, and policy makers accountable and to address these leaks [@HEET_2017].
## Another gas disaster reveals systemic problems
In September 2018, concerns about the dangers of natural gas rose to the forefront again after a series of natural gas explosions and fires hit three communities in the Merrimack Valley of northeastern Massachusetts. As a result of overpressurization during gas line replacement by Columbia Gas, five homes were destroyed, and another 131 damaged by fire. One 18-year old man was killed, and 19 others hospitalized. Approximately 50,000 people were forced to evacuate the area. The City of Lawrence, a largely Hispanic, immigrant, and working-class community, was hardest hit by the crisis, accounting for all of the direct injuries and most of the property damage [@NTSB_2019; @Walters_2019; @Valencia_2020].
While the disaster was regarded as an unusual event, other investigations have highlighted systemic problems in how natural gas utilities across the state prioritize and handle gas leaks. Research released in 2016 showed that just 7% of leaks in the greater Boston distribution system accounted for 50% of gas leak emissions by volume [@Hendrick_Ackley_2016]. Moreover, these “super emitters” were just as likely to be Class 3 leaks, which are not considered an explosion hazard and thus are not normally prioritized for repair. Massachusetts subsequently passed legislation requiring utilities to identify and prioritize these leaks of “significant environmental impact” or SEIs [@EnergyDiversityAct]. Since 2017, HEET has collaborated with the state's largest gas utilities to help them adopt a reliable and proven new method for accurately identifying SEIs [@HEET2021]. However, leak repair is not always successful. HEET and others have found empirically that gas was still detectable in about 70% of cases where leaks were reported as “repaired” [@HEET2021; @Edwards2021].
An outside auditor contracted by the state in response to the Columbia Gas disaster found that most of the gas utilities in the state were moving too slowly in pipeline replacement to meet statutory obligations, were plagued by poor record keeping, inconsistent methods of leak monitoring and repair, and curiously, were improperly prioritizing repairs in suburban communities, rather than in more densely populated urban communities where more people were exposed and the risks higher [@Herdes_Campbell_2020].
Sustained attention to the problem of leaking natural gas for the last decade in Massachusetts has spurred awareness about the magnitude and extent of the problem. Most of this attention has been premised on concerns about greenhouse gas mitigation, cost recovery, and public safety. With very few exceptions [@Mascoop_2018; @Scott_Scott_2019], these conversations have not considered the distributional or equity dimensions of the problem and response to gas leaks; an environmental justice perspective.
## An Environmental Justice framework
Environmental justice is the principle that everyone has a right to a healthy environment and to be treated fairly, with meaningful opportunity for participation in processes or decisions that affect them. In practice, environmental justice is rooted in the recognition that specific communities and population groups – particularly People of Color and lower income people – have been denied these rights.
Since the 1980s, government reports, academic scholarship, and investigative journalism have repeatedly found that People of Color and low income communities across the country are disproportionately exposed or vulnerable to a wide range of environmental burdens, including hazardous waste [@Salazar_Clauson_2019], air pollution [@Colmer_Hardman_2020], water pollution [@Schaider_2019], noise pollution [@Collins_Nadybal_2020], traffic [@Pinto_Reichmuth_2019], and more recently, the climate change enhanced risks of flooding [@Hardy_Milligan_2017], excessive heat [@Hoffman_Shandas_2020], and extreme weather [@García-López_2018]. Conversely, these same communities and groups are disproportionately denied environmental benefits or amenities, such as access to greenspace [@Rigolon_Browning_2018], urban tree canopy coverage [@Schwarz_Fragkias_2015], lead-free housing [@Whitehead_LaToria_2019], access to safe drinking water [@Fedinick_Taylor_2019], and equal environmental compliance [@McDonald_Jones_2018] and enforcement [@Konisky_Reenock_2018]. These burdens do not occur singly or in isolation, but are overlapping, cumulative, and synergistic in their effects on health and wellbeing and even economic opportunity.
The focus of an environmental justice perspective is therefore on:
* those communities that have been, and continue to be, disproportionately burdened by pollution and other environmental insults,
* those who are especially vulnerable to risks and threats,
* those who have been unfairly excluded from enjoying environmental benefits, and
* those who have been denied a voice in decision making about their environments – “where they live, work, and play” (Robert Bullard quoted in Schweizer 1999).
Natural gas leaks should be evaluated through an environmental justice framework. Gas leaks are environmental problems with global and local impacts, and these impacts are unequal. Methane is an exceptionally powerful greenhouse gas. Because lower income communities and People of Color are more vulnerable to the effects of climate change, the consequences of delay or inaction are inherently inequitable. Methane also contributes significantly to the formation of ground-level ozone [@West_Fiore_2006], an air pollutant with serious public health impacts, especially for people with asthma or other respiratory sensitivities. People of Color, particularly children, suffer from asthma at rates two to three times that of their White counterparts [@ALA2021; @Keet_Matsui_2017]. Gas leaks have also been shown to damage or kill street trees [@Schollaert_2020], which is especially significant for communities already lacking adequate tree coverage [@Namin_Xu_2020; @McDonald_Jones_2018] and the climate benefits and risk mitigation those trees offer [@Ferrini_Fini_2020]. Utilities pass on the costs of lost gas to ratepayers. For lower income households and People of Color who already experience higher energy burdens [@Drehobl_Ross_2020], the added costs of this undelivered gas have a regressive impact. And finally, of course, the presence of gas leaks always carries the risk of explosions, fires, or disruption.
At its core, environmental justice is about the spatial distribution of environmental benefits and burdens [@Lee_2021]. This is because environmental phenomena are inherently geographic, and because *where* something happens (and the significance of its impact) is often closely related to *who* lives there. This analysis applies an environmental justice analysis to the phenomenon of natural gas leaks in Massachusetts using a geospatial approach to quantitatively describe and compare the experiences of different population groups with respect to both exposure to gas leaks and to the timeliness of their repair.
# Data and methods
## Data
Gas leaks data for this analysis were acquired from HEET (https://heet.org/gas-leaks/gas-leak-maps/). HEET’s data on gas leaks is derived from Annual Service Quality Reports (ASQR) that are submitted by investor-owned utilities to the DPU each February, which reflect gas leak activity for the previous calendar year [@HEET_2021; @GasLeakAct]. HEET geocoded the leaks based on their reported addresses or cross-street locations and performed extensive quality control on the results. HEET’s gas leak data contain all of the original data reported in the AQSRs, including addresses, date first reported, and leak class or grade (i.e., explosive hazard) of individual repaired and unrepaired gas leaks for each utility for one year – January 1 through December 31, 2019.
Gas leak data was disaggregated by repaired or unrepaired status and also by leak class or grade. For this analysis, leak class and grade are used synonymously. Under Massachusetts law (220 CMR 114.04), leaks are classified by utilities according to the following classification system:
* Grade 1 represents “an existing or probable hazard to persons or property.” Requires “immediate commencement of repair and continuous action until the conditions are no longer hazardous, the source of the leak is eliminated, and permanent repairs have been completed.”
* Grade 2 is recognized as “nonhazardous to persons or property at the time of detection, but justifies scheduled repair based on probable future hazard.” Must be repaired within 12 months from the date the leak was classified. Must be reevaluated at least once every six months until eliminated.
* Grade 3 is recognized as “nonhazardous to persons or property at the time of detection and can be reasonably expected to remain nonhazardous.” Must be reevaluated during the next scheduled survey, or within 12 months from the date last evaluated, whichever occurs first. Leaks classified on or after January 1, 2018 must be repaired or eliminated within eight years.
As of 2018, gas utilities are also required to repair environmentally significant grade 3 leaks (SEIs) on an accelerated schedule, within one to two years depending on the leak extent. SEIs are not evaluated separately here due to the current variability in classification accuracy. Classification accuracy is expected to improve over time and should be reevaluated in the future as a separate category.
In their ASQRs, all utilities reported leaks that were in a "repaired" or "unrepaired" status at the end of 2019. Some of the utilities reported that some leaks were in an "eliminated" status, either due to pipeline replacement Gas System Enhancement Programs (GSEPs), or other reasons (for example, resurveys not finding gas at leak locations). These eliminated leaks were not consistently reported by all utilities in their ASQRs and may have been prioritized and repaired differently to the other "repaired" leaks. We chose not to include them in this analysis and recommend further research be focused on GSEPs and prioritization.
Population data was derived from the American Community Survey 5-year estimates for 2015-2019 at the Census Block Group level, Census Tract level, and the municipality level (i.e., Census County Subdivisions) via the tidycensus package version 0.11.4 in R (Walker and Herman 2021).
## Methodology
### Population-weighted mean exposure
Exposure to gas leaks was measured as the population-weighted mean gas leaks density within the geographic unit of analysis (i.e., Block Group, Tract, or municipality). For example, gas leak density is calculated as the number of reported gas leaks in a Block Group divided by the area of the Block Group in square kilometers. Population-weighted mean gas leaks density is calculated by multiplying the gas leaks density of each Block Group and the respective population groups of the same Block Groups to get weighted values, from which a weighted mean is calculated. Only Block Groups falling within the natural gas utility service areas providing leak data were included in the analysis.
A population-weighted mean is calculated according to the following formula:
$$ \overline{x}_w = \frac{\sum_{i=1}^{n} (x_i \times w_i)}{\sum_{i=1}^{n}w_i} $$
where $\overline{x}_w$ is the population-weighted mean of some variable, in this case gas leak density;
where ${x_i}$ represents an individual observation, in this case the leak density of a Block Group;
where ${w_i}$ is the weight associated with an observation, in this case the population of a block group.
Population-weighted means are a common approach in analyses of the distribution of environmental burdens and amenities, particularly when comparing between population subgroups [@Bell_Ebisu_2012; @Mikati_Benson_2018; @Richmond-Bryant_Mikati_2020]. The US Environmental Protection Agency (EPA) uses population-weighted means as the primary way of expressing exposure differentials to a variety of environmental burdens in its nationwide EJSCREEN application (https://www.epa.gov/ejscreen). One of the advantages of a population-weighted approach is that population estimates for Census statistical units (i.e., Block Groups or Tracts) are not correlated with population density. This is because Census units are constructed to have similar population sizes. In Massachusetts, over 90% of Block Groups have populations between 565 and 2,700 for the 2015-2019 period. This means population weighting does not emphasize urban or high-density locations. If population-weighted gas leak density is higher in denser, more urban areas, this difference is not due to population weighting. Instead, this difference likely reflects the underlying phenomenon itself or other drivers of the phenomenon [@EPA_2019].
### Relative exposure
To better compare differences between groups, results are presented as relative exposures. Relative exposure is calculated similarly to relative risk or risk ratio:
$$ RE = \frac{\overline{x}_w subgroup} {\overline{x}_w total pop} $$
where $RE$ is the relative exposure expressed as a ratio;
where $\overline{x}_w subgroup$ is the population-weighted mean exposure of a subgroup, such as People of Color;
where $\overline{x}_w total pop$ is the population-weighted mean exposure of the total or comparison population.
Relative exposure values greater than one indicate that the subgroup is more exposed than the general population. Values less than one indicate that the subgroup is less exposed than the general population. For example, a relative exposure of 1.5 would indicate that a group has an exposure that is 1.5 times that of, or 50% greater than, the total population. Risk or relative exposure ratios are common in both public health and in studies of environmental justice because of their simplicity in making comparisons and communicating differences in exposure between groups [@Debbage_2019; @Mikati_Benson_2018; @Harner2002].
For this analysis, relative exposures are calculated relative to the general population ACS estimates. For relative exposure by race, ethnicity, and income, total population estimates are used as the denominator. Total households are used as the denominator for household-level relative exposure. Total occupied housing units are used as the denominator for housing-unit level relative exposure, such as housing tenure or housing burden.
### Sensitivity Analyses
To assess potential bias from analytic choices, we performed sensitivity analyses to account for the impact of differences in definitions of vulnerable populations, uncertainty in ACS population estimates, and choices in scale or the geographic unit of analysis.
This analysis looks at variations in exposure for a variety of demographic groups that environmental justice policy and research have identified as being especially vulnerable to environmental burdens, or deprived of environmental benefits, as a consequence of social or economic disadvantage, physical vulnerability, or historic and persistent discrimination and inequality. These groups include:
* People of Color (i.e., persons who are of Hispanic ethnicity or racially not White, including indigenous populations)
* In addition to the aggregate category of “People of Color”, non-Hispanic Asians, non-Hispanic Blacks, Hispanics, and non-Hispanic Whites were analyzed separately as well
* Low income persons (i.e., income less than twice the poverty line)
* Limited-English speaking households (i.e., households where no one over the age of 14 speaks English “very well”)
* Adults 25 years or older without a high school diploma
* Children under the age of 5
* Adults over the age of 64
* Disabled adults
* Renters
* Housing burdened households (i.e., households paying more than 30% of household income to rent or mortgage)
* People living in Environmental Justice communities as defined by the 2021 *Climate Roadmap* legislation, which capture Census Block Groups with high proportions of People of Color, limited English speaking households, or lower income persons. Massachusetts Environmental Justice communities are represented by the prefix ‘MA’.
Population numbers for this analysis were derived from the ACS 5-year estimates for the period 2015-2019. After the 2000 census, detailed data on demographic characteristics (e.g., income, education, housing) are only available from the ACS. While the decennial Census is based on a total enumeration of the population at one point in time, ACS estimates are based on a rolling sample of responses – about 3.5 million annually across the country – which are pooled from surveys compiled on a monthly basis across the year [@ACS_2020]. For small areas with populations less than 65,000, estimates are only available as pooled 5-year estimates. Because the ACS is based on a sample, estimates are subject to uncertainty or sampling error. This uncertainty is communicated through a Margin of Error (MOE) which accompanies each ACS estimate. For some population subgroups, such as racial and ethnic minorities, children, and renters, Census response rates can be low and uncertainty high [@OHare_2019]. Moreover, smaller geographic units, such as Block Groups, will also tend to have higher MOEs because they are derived from small samples. One approach to dealing with the high MOE of small area estimates is to aggregate groups (e.g., combining individual racial categories into one ‘People of Color’ category) or to use larger geographic units (e.g., Census Tracts rather than Census Block Groups). Both techniques reduce uncertainty for estimates, although this reduced uncertainty comes at the expense of demographic or spatial resolution. Both methods – aggregating groups and using larger geographic units - are applied here to consider the impacts of uncertainty and aggregation.
A separate but related issue to the uncertainty of sampling and estimation is the Modifiable Areal Unit Problem (MAUP). MAUP refers to the fact that analytical results can be influenced by the geographic size or shape of units of analysis. In other words, different geographic definitions of a study area may result in different outcomes. The MAUP is a long-recognized challenge in geographic analysis [@Openshaw_Taylor_1979], but analysts are often constrained by data availability (e.g., administrative databases, sensor resolution, reporting conventions), as well as by lack of clear guidance or theory on an appropriate geographic unit of analysis [@Dark_Bram_2007]. Varying both the areal size and shape of the units of analysis can show whether results are dependent on choices for the scale and shape of the unit of analysis. Although cumbersome, this is recommended practice in environmental justice analyses [@Cutter_Holm_1996; @Baden_Noonan_Turaga_2007; @Karner2013]. To explore the impact of geographic scale and choice of unit of analysis, we replicated our analyses at the Census Block Group level, Census Tract level, and municipality level (i.e., Census County Subdivision) (see Figure \@ref(fig:MAUP)).
```{r MAUP, fig.align = "center", fig.cap="Comparison of scales and units of analysis: municipality (i.e., Census County Subdivision), Census Tract, and Census Block Group", echo=FALSE, message=FALSE}
# # create a graphic to illustrate relationship of block groups, tracts, and county subdivisions
# library(tidyverse)
# library(tigris)
# library(tmap)
# library(sf)
# library(tmaptools)
#
# ma_counties <- counties(state = "MA", cb = TRUE) %>%
# filter(NAME == "Suffolk")
# # ma_cosub <- county_subdivisions(state = "MA", cb = TRUE, county = "025") %>%
# # filter(NAME == "Chelsea") # NOT WORKING ALL OF SUDDEN ON 5/13/2021
# # Download file directly from https://www2.census.gov/geo/tiger/TIGER2019/
# ma_cosub <- st_read(dsn = "Data/tl_2019_25_cousub", layer = "tl_2019_25_cousub")%>%
# filter(NAME == "Chelsea")
# ma_tracts <- tracts(state = "MA", cb = TRUE, county = "025")
# ma_blkgrps <- block_groups(state = "MA", cb = TRUE, county = "025")
#
#
# # isolate tracts in Chelsea
# ma_tracts_chelsea <- ma_tracts %>%
# select(GEOID) %>%
# st_centroid() %>%
# filter(st_intersects(., ma_cosub, sparse = FALSE)) %>%
# as.data.frame() %>%
# right_join(ma_tracts, ., by = "GEOID")
#
# # tm_shape(ma_tracts_chelsea) + tm_borders() +
# # tm_shape(ma_tracts_chelsea) + tm_text(text = "NAME") #25025160101
#
# # isolate tract
# ma_tracts_1 <- ma_tracts_chelsea %>%
# filter(GEOID == "25025160101")
#
# # isolate blockgroups within tract
# ma_blkgrp_1 <- ma_blkgrps %>%
# filter(str_starts(GEOID, "25025160101"))
#
# # tm_shape(ma_blkgrp_1) + tm_borders() +
# # tm_shape(ma_blkgrp_1) + tm_text(text = "NAME")
#
# # isolate a single block group within the tract
# ma_blkgrp_4 <- ma_blkgrp_1 %>%
# filter(NAME == "1")
#
# # create separate maps for each level
# # tmap_mode("plot")
# # first, create basemaps for each
# a_bm <- ma_counties %>%
# st_transform(., crs = 4326) %>%
# st_bbox(.) %>%
# tmaptools::read_osm(., type = "esri")
#
# # create a new bbox so that Chelsea map fills space
# bbox_new <- st_bbox(ma_cosub)
#
# xrange <- bbox_new$xmax - bbox_new$xmin # range of x values
# yrange <- bbox_new$ymax - bbox_new$ymin # range of y values
#
# # bbox_new[1] <- bbox_new[1] - (0.5 * xrange) # xmin - left
# # bbox_new[3] <- bbox_new[3] + (0.5 * xrange) # xmax - right
# bbox_new[2] <- bbox_new[2] - (0.13 * yrange) # ymin - bottom
# bbox_new[4] <- bbox_new[4] + (0.1 * yrange) # ymax - top
#
# bbox_new <- bbox_new %>% # take the bounding box ...
# st_as_sfc() # ... and make it a sf polygon
#
# b_bm <- bbox_new %>%
# st_transform(., crs = 4326) %>%
# st_bbox(.) %>%
# tmaptools::read_osm(., type = "esri")
#
# # create a new bbox so that Block Group map fills space
# bbox_new2 <- st_bbox(ma_tracts_1)
#
# xrange <- bbox_new2$xmax - bbox_new2$xmin # range of x values
# yrange <- bbox_new2$ymax - bbox_new2$ymin # range of y values
#
# bbox_new2[1] <- bbox_new2[1] - (0.06 * xrange) # xmin - left
# bbox_new2[3] <- bbox_new2[3] + (0.06 * xrange) # xmax - right
# bbox_new2[2] <- bbox_new2[2] - (0.04 * yrange) # ymin - bottom
# bbox_new2[4] <- bbox_new2[4] + (0.01 * yrange) # ymax - top
#
# bbox_new2 <- bbox_new2 %>% # take the bounding box ...
# st_as_sfc() # ... and make it a sf polygon
#
# c_bm <- bbox_new2 %>%
# st_transform(., crs = 4326) %>%
# st_bbox(.) %>%
# tmaptools::read_osm(., type = "esri")
#
# # make the maps
# a <- tm_shape(a_bm) + tm_rgb() +
# tm_shape(ma_counties) + tm_fill(col = "gray88", alpha = 0.8) +
# tm_shape(ma_cosub) + tm_borders(col = "#7570b3", lwd = 3) +
# # tm_shape(ma_tracts_1) + tm_fill(col = "#d95f02") +
# # tm_shape(ma_blkgrp_4) + tm_fill(col = "#1b9e77") +
# tm_scale_bar(breaks = c(0,5,10), position = c("center","BOTTOM")) +
# tm_layout(title = "Municipality (i.e., Census\nCounty Subdivision)",
# inner.margins = c(0.03,0.02,0.18,0.02))
#
# b <- tm_shape(b_bm) + tm_rgb() +
# tm_shape(ma_cosub, unit = "km") + tm_fill(col = "gray88", alpha = 0.8) +
# tm_shape(ma_tracts_1) + tm_fill(col = "#d95f02") +
# # tm_shape(ma_blkgrp_4) + tm_fill(col = "#1b9e77") +
# tm_shape(ma_cosub) + tm_borders(col = "#7570b3", lwd = 3) +
# tm_credits("Tract", position = c(0.49,0.22)) +
# tm_credits("Municipality", position = c(0.38,0.45),
# col = "#7570b3", alpha = 0.7) +
# tm_scale_bar(breaks = c(0,1,2), position = c("center","BOTTOM")) +
# tm_layout(title = "Census Tract within\nMunicipality", title.size = 0.9,
# inner.margins = c(0.01,0.02,0.16,0.02))
#
# c <- tm_shape(c_bm, unit = "m", bbox = ma_tracts_1) + tm_rgb() +
# tm_shape(ma_tracts_1, unit = "m") + tm_fill(col = "gray88", alpha = 0.8) +
# tm_shape(ma_blkgrp_4) + tm_fill(col = "#1b9e77") +
# tm_shape(ma_tracts_1) + tm_borders(col = "#d95f02", lwd = 3) +
# tm_credits("Block\nGroup", position = c(0.19,0.41)) +
# tm_credits("Census Tract", position = c(0.38,0.30),
# col = "#d95f02", alpha = 0.7) +
# tm_scale_bar(breaks = c(0,250,500), position = c("center","BOTTOM")) +
# tm_layout(title = "Census Block Group\nwithin Census Tract", title.size = 0.9,
# inner.margins = c(0.1,0,0.21,0))
#
# tmap_arrange(a,b,c, ncol = 3) %>%
# tmap_save(., filename = "Images/pub/census_geog.png",
# width = 6, height = 3, units = "in")
knitr::include_graphics("Images/pub/census_geog.png")
```
# Results
```{r data, include=FALSE}
# load packages and data
library(tidyverse)
library(sf)
library(tigris)
library(tmap)
library(tmaptools)
library(ggplot2)
library(foreign) # for reading in dbf
# library(tidytext) # for reorder_within and scale_x_reorder in ggplot2 facets
library(kableExtra)
# library(sp)
# library(spdep)
library(tigris)
# library(bibtex)
# Load demographic and gas leaks data
load("Data/Demographics.rds")
load("Data/HEET2019Leaksv2.rds")
ma_blkgrps <- readRDS("Data/ma_blkgrps2019.Rds")
ma_tracts <- readRDS("Data/ma_tracts2019.Rds")
ma_cosub <- readRDS("Data/ma_cosub2019.Rds")
ppLeakDensity_df_bg <- readRDS("Data/ppLeakDensity_df_blkgrps2019.Rds")
ppLeakDensity_df_tr <- readRDS("Data/ppLeakDensity_df_tracts2019.Rds")
ppLeakDensity_df_co <- readRDS("Data/ppLeakDensity_df_cosubs2019.Rds")
ppLeakDensityJoinedU_bg <- readRDS("Data/ppLeakDensityJoinedU_BG2019.Rds")
ppLeakDensityJoinedU_tr <- readRDS("Data/ppLeakDensityJoinedU_TR2019.Rds")
ppLeakDensityJoinedU_co <- readRDS("Data/ppLeakDensityJoinedU_CO2019.Rds")
# set common CRS
unrepaired2019 <- st_transform(unrepaired2019, crs = st_crs(ma_blkgrps))
repaired2019 <- st_transform(repaired2019, crs = st_crs(ma_blkgrps))
# Set up recurring map elements
# Load natural gas utility service areas dbf from MassGIS and join to MassGIS towns layer
ng_dbf <- read.dbf("Data/pubutil/TOWNS_POLY_UTILITIES.dbf")
ng_service_areas <- st_read(dsn = "Data/townssurvey_shp",
layer = "TOWNSSURVEY_POLYM") %>%
select(-TOWN) %>%
left_join(., ng_dbf, by = "TOWN_ID") %>%
select(TOWN, GAS, GAS_LABEL) %>%
st_transform(., crs = st_crs(ma_blkgrps)) %>%
st_make_valid()
# isolate No gas areas and municipal
ng_nogas_muni <- ng_service_areas %>%
filter(GAS_LABEL %in% c("No Natural Gas Service","Municipal")) %>%
group_by(GAS_LABEL) %>%
summarize() %>%
mutate(GAS_LABEL = as.character(GAS_LABEL))
# consolidate into basic gas service districts
ng_service_areas2 <- ng_service_areas %>%
filter(!GAS_LABEL %in% c("No Natural Gas Service","Municipal")) %>%
group_by(GAS_LABEL) %>%
summarize(TownCnt = n()) %>%
mutate(ID = case_when(
GAS_LABEL == "National Grid" ~ "NG",
GAS_LABEL == "Blackstone Gas Company" ~ "BGC",
GAS_LABEL == "Columbia Gas" ~ "CG",
GAS_LABEL == "Eversource Energy" ~ "EV",
GAS_LABEL == "Columbia Gas, Eversource Energy" ~ "CG,EV",
GAS_LABEL == "Unitil" ~ "UN",
GAS_LABEL == "National Grid, Unitil" ~ "NG,UN",
GAS_LABEL == "Eversource Energy, National Grid" ~ "EV,NG",
GAS_LABEL == "The Berkshire Gas Company" ~ "BG",
GAS_LABEL == "Columbia Gas, Blackstone Gas Company" ~ "CG,BGC",
GAS_LABEL == "Liberty Utilities" ~ "LU",
GAS_LABEL == "Colonial Gas" ~ "NG",
GAS_LABEL == "Columbia Gas, National Grid" ~ "CG,NG"
))
# join ID to original municipalities within ng_service_area to use centroids as labels; restrict to central municipalities within territories
ng_service_labels <- ng_service_areas2 %>%
as.data.frame() %>%
select(ID, GAS_LABEL) %>%
inner_join(ng_service_areas, ., by = "GAS_LABEL") %>%
filter(TOWN %in% c("LANESBOROUGH","DEERFIELD","NORTHAMPTON","LUDLOW",
"NORTH BROOKFIELD","OXFORD",
"WESTMINSTER","CARLISLE","ANDOVER","WESTBOROUGH",
"BLACKSTONE","MILTON",
"NORWOOD","WEST BRIDGEWATER","PLAINVILLE","PLYMOUTH",
"WESTPORT","ACUSHNET","WAREHAM","BARNSTABLE",
"SWANSEA","MARSHFIELD","COHASSET",
"HAMILTON","WEST NEWBURY","DOVER","DUNSTABLE")) %>%
st_centroid(., of_largest_polygon = TRUE)
ng_service_labels2 <- ng_service_areas2 %>%
as.data.frame() %>%
select(ID, GAS_LABEL) %>%
inner_join(ng_service_areas, ., by = "GAS_LABEL") %>%
filter(TOWN %in% c("LEICESTER","LUNENBURG","MENDON","BELLINGHAM","HANSON",
"WAYLAND","NATICK","BOSTON","SOMERVILLE")) %>%
st_centroid(., of_largest_polygon = TRUE)
ng_service_labels3 <- ng_service_areas2 %>%
as.data.frame() %>%
select(ID, GAS_LABEL) %>%
inner_join(ng_service_areas, ., by = "GAS_LABEL") %>%
filter(TOWN == "BOSTON") %>%
st_centroid(., of_largest_polygon = TRUE)
# separate MA for cropping
ma_state_sf <- states(cb = TRUE) %>%
filter(STUSPS == "MA")
# grab municipal boundaries
# ma_towns_sf <- county_subdivisions(state = "MA", cb = TRUE) %>%
# st_transform(., crs = 26986) # breaking periodically
# Download file directly from https://www2.census.gov/geo/tiger/TIGER2019/
ma_towns_sf <- st_read(dsn = "Data/tl_2019_25_cousub",
layer = "tl_2019_25_cousub") %>%
st_transform(., crs = 26986)
# create point layer of towns for context
ma_towns_sf_pts <- ma_towns_sf %>%
# county_subdivisions(state = "MA", cb = TRUE) %>%
filter(NAME %in% c("Boston",
"Lawrence",
"Lowell",
"Brockton",
"Worcester",
"Springfield",
"Pittsfield",
"Stockbridge",
"Fall River",
"West Yarmouth",
"Lynn",
"Randolph",
"Webster",
"Attleboro",
"Medford",
"Amherst",
"Quincy",
"Weymouth Town",
"Nantucket")) %>%
mutate(NAME = recode(NAME, "Weymouth Town" = "Weymouth")) %>%
st_transform(., crs = 26986) %>%
st_centroid(of_largest_polygon = TRUE)
# create a separate point for Newton so that it can be repositioned
newton <- ma_towns_sf %>%
# county_subdivisions(state = "MA", cb = TRUE) %>%
filter(NAME %in% c("Fitchburg","Newton","Edgartown","New Bedford")) %>%
st_transform(., crs = 26986) %>%
st_centroid(of_largest_polygon = TRUE)
```
In calendar year 2019, there were `r format(nrow(unrepaired2019)+nrow(repaired2019), big.mark = ",")` natural gas leaks in the distribution system reported by six of the seven investor-owned utilities in Massachusetts that filed leak reports with the DPU. These utilities represent 98% of natural gas customers in the state [@AGA].[^d] Repairs were reported for `r format(nrow(repaired2019), big.mark = ",")` (`r round(nrow(repaired2019)/(nrow(unrepaired2019)+nrow(repaired2019)),2)*100`%) of these, leaving `r format(nrow(unrepaired2019), big.mark = ",")` (`r round(nrow(unrepaired2019)/(nrow(unrepaired2019)+nrow(repaired2019)),2)*100`%) unrepaired leaks across the state as of December 31, 2019 (see Table \@ref(tab:tabLeaks)).
[^d]: No gas leak data was reported by Blackstone Gas Company.
```{r tabLeaks, echo=FALSE, message=FALSE, warning=FALSE, fig.align='center'}
# table of leak stats by class and repair status
unrepaired_Sumdf <- unrepaired2019 %>% as.data.frame() %>%
group_by(Class) %>% summarize(Unrepaired = n())
repaired_Sumdf <- repaired2019 %>% as.data.frame() %>%
group_by(Class) %>% summarize(Repaired = n())
total_Sumdf <- left_join(unrepaired_Sumdf, repaired_Sumdf, by = "Class") %>%
drop_na() %>%
mutate(Total = Unrepaired + Repaired) %>%
bind_rows(summarize(.,
across(where(is.numeric), sum),
across(where(is.character), ~ "Total"))) %>%
mutate(PctUnrepaired = Unrepaired/Total*100,
PctRepaired = Repaired/Total*100,
PctTotal = Total/Total[Class == "Total"]*100) %>%
select(Class, Unrepaired, PctUnrepaired, Repaired, PctRepaired,
Total, PctTotal)
total_Sumdf %>%
mutate(PctUnrepaired = paste0(round(PctUnrepaired,1),"%"),
PctRepaired = paste0(round(PctRepaired,1),"%"),
PctTotal = paste0(round(PctTotal,1),"%")) %>%
kable(., longtable = T, booktabs = T,
format.args = list(big.mark = ','),
caption = "Gas leaks by class and repair status, 2019", align = "r",
# digits = c(0,0,1,0,1,0,1),
col.names = c("Class","Count","Percent","Count","Percent",
"Total","Pct Total")) %>%
add_header_above(., c(" ", "Unrepaired Leaks" = 2, "Repaired Leaks" = 2,
" " = 2)) %>%
row_spec(4, bold = T) %>%
kable_styling(latex_options = c("repeat_header"))
```
Reported gas leaks were nearly ubiquitous across the state (see Figures \@ref(fig:mapAllLeaks) - \@ref(fig:mapAllLeaksCO)). At least one gas leak was reported in `r round((ma_cosub %>% filter(AllLeaks2019>0) %>% nrow())/nrow(ma_cosub)*100,0)`% of the municipalities within natural gas service territories, and `r round((ma_cosub %>% filter(unrepaired2019total>0) %>% nrow())/nrow(ma_cosub)*100,0)`% had at least one unrepaired gas leak at the end of 2019. Over `r round((ma_blkgrps %>% filter(AllLeaks2019>0) %>% nrow())/nrow(ma_blkgrps)*100,0)`% of Census Block Groups had at least one known gas leak, and approximately `r round((ma_blkgrps %>% filter(unrepaired2019total>0) %>% nrow())/nrow(ma_blkgrps)*100,0)`% had at least one unrepaired gas leak at the end of 2019. However, there was significant variation in geographic distribution and concentration of these leaks.
```{r mapAllLeaks, fig.align='center', fig.cap= "Massachusetts Gas Leaks and Utility Territories, 2019, aggregated by 1km hexagon tessellations", cache=TRUE}
# Map of leak counts by hexagons and utility territories
# create a hexagonal grid and create index column
gridCnt <- st_make_grid(x = ma_blkgrps, cellsize = 1000, square = FALSE) %>%
st_as_sf() %>%
mutate(index = row_number())
# spatially join to grid ids to leaks, sum aggregate numbers of leaks per grid index, and then join sums back to hexagons for mapping and analysis
gridCnt <- unrepaired2019 %>%
st_join(., gridCnt) %>%
st_drop_geometry() %>%
group_by(index) %>%
summarize(unrepaired = n()) %>%
left_join(gridCnt, ., by = "index") %>%
replace_na(list(unrepaired = 0))
gridCnt <- repaired2019 %>%
st_join(., gridCnt) %>%
st_drop_geometry() %>%
group_by(index) %>%
summarize(repaired = n()) %>%
left_join(gridCnt, ., by = "index") %>%
replace_na(list(repaired = 0))
# create column with total leak points and clip to MA
gridCnt <- gridCnt %>%
mutate(total = unrepaired + repaired) %>%
crop_shape(., ma_blkgrps, polygon = TRUE) %>%
st_make_valid()
gridCntT <- gridCnt %>%
filter(total > 0)
m_gridTotal <- tm_shape(gridCntT, unit = "km", bbox = ma_state_sf) +
tm_fill(col = "total", palette = "YlOrRd",
style = "fisher",
# breaks = c(1,5,10,20,40,80),
legend.format = list(digits = 0),
title = "Number\nof leaks") +
tm_shape(ng_nogas_muni, bbox = ma_state_sf) +
tm_fill(col = "GAS_LABEL", palette = c("ivory2","gray88"), title = "",
legend.show = FALSE) +
tm_shape(ng_service_areas2) + tm_borders(lwd = 0.8, col = "grey68", alpha = 0.7) +
tm_shape(ng_service_labels) +
tm_text("ID", size = 0.6, col = "gray") +
tm_shape(ng_service_labels2) +
tm_text("ID", size = 0.4, col = "gray") +
tm_shape(ng_service_labels3) +
tm_text("ID", size = 0.6, col = "gray", xmod = 2.7, ymod = 0.7) +
# tm_shape(EJlayer) + tm_borders(col = "blue", alpha = 0.7) +
tm_shape(ma_towns_sf_pts) + tm_dots() +
tm_text("NAME", size = 0.4, col = "black",
xmod = 0.7, ymod = 0.2, shadow = TRUE) +
tm_shape(newton) + tm_dots() +
tm_text("NAME", size = 0.4, col = "black",
xmod = -0.7, ymod = 0.2, shadow = TRUE) +
tm_scale_bar(breaks = c(0,25,50), position = c("left","BOTTOM")) +
tm_layout(legend.position = c(0.055,0.1),
title = "Massachusetts Gas Leaks and Utility Territories, 2019",
title.size = 0.9,
inner.margins = c(0.02,0.02,0.09,0.02)
) +
tm_credits("BG = Berkshire Gas\nBGC = Blackstone Gas Co.\nCG = Columbia Gas\nEV = Eversource Energy\nLU = Liberty Utilities\nNG = National Grid\nUN = Unitil/Fitchburg Gas", position = c(.3,.11), col = "gray47", size = 0.7)
# create insets with dummy layers to create separate legend items
d_inset <- tm_shape(ng_nogas_muni) + tm_fill(alpha = 0) +
tm_add_legend(type = "fill", col = "ivory2", labels = "Municipal Utility",
border.col = "white") +
tm_layout(legend.position = c(0.33,0.06), bg.color = NA, frame = FALSE,
legend.text.color = "gray47")
d_inset2 <- tm_shape(ng_nogas_muni) + tm_fill(alpha = 0) +
tm_add_legend(type = "fill", col = "gray88", labels = "No Natural Gas Service",
border.col = "white") +
tm_layout(legend.position = c(0.33,0.025), bg.color = NA, frame = FALSE,
legend.text.color = "gray47")
# create viewports to specify dimensions of insets
vp_inset <- grid::viewport(x = 0.5, y = 0.5, width = 3, height = 1)
vp_inset2 <- grid::viewport(x = 0.5, y = 0.5, width = 3, height = 1)
tmap_save(m_gridTotal, filename = "Images/pub/m_gridTotalUtil.png",
dpi = 600, height = 4, width = 8, units = "in",
insets_tm = list(d_inset,d_inset2),
insets_vp = list(vp_inset,vp_inset2))
knitr::include_graphics("Images/pub/m_gridTotalUtil.png")
```
```{r mapAllLeaksBG, fig.align='center', fig.cap= "Massachusetts gas leaks per square kilometer by Census Block Group, 2019", cache=TRUE}
# create map of leak densities by BG
blkgrpsLeaksAll <- ma_blkgrps %>%
filter(AllLeaks2019_sqkm > 0)
m1 <- tm_shape(blkgrpsLeaksAll, bbox = ma_state_sf) +
tm_fill(col = "AllLeaks2019_sqkm", style = "fisher", palette = "YlOrRd",
title = "Leaks per SqKm", legend.format = list(digits = 2)) +
tm_shape(ng_nogas_muni) +
tm_fill(col = "GAS_LABEL", palette = c("ivory2","gray88"), title = "",
legend.show = FALSE) +
tm_shape(ma_blkgrps) + tm_borders(lwd = 0.01, alpha = 0.8) +
tm_shape(ng_service_areas2) +
tm_borders(lwd = 0.8, col = "grey68", alpha = 0.7) +
tm_shape(ng_service_labels) +
tm_text("ID", size = 0.6, col = "gray") +
tm_shape(ng_service_labels2) +
tm_text("ID", size = 0.4, col = "gray") +
tm_shape(ng_service_labels3) +
tm_text("ID", size = 0.6, col = "gray", xmod = 2.7, ymod = 0.7) +
# tm_shape(EJlayer) + tm_borders(col = "blue", alpha = 0.7) +
tm_shape(ma_towns_sf_pts) + tm_dots() +
tm_text("NAME", size = 0.4, col = "black",
xmod = 0.7, ymod = 0.2, shadow = TRUE) +
tm_shape(newton) + tm_dots() +
tm_text("NAME", size = 0.4, col = "black",
xmod = -0.7, ymod = 0.2, shadow = TRUE) +
tm_scale_bar(breaks = c(0,25,50), position = c("left","BOTTOM")) +
tm_layout(legend.position = c(0.050,0.15),
title = "Massachusetts Gas Leak Density by Census Block Group and Utility Territories, 2019",
inner.margins = c(0.02,0.02,0.09,0.02)) +
tm_credits("BG = Berkshire Gas\nBGC = Blackstone Gas Co.\nCG = Columbia Gas\nEV = Eversource Energy\nLU = Liberty Utilities\nNG = National Grid\nUN = Unitil/Fitchburg Gas", position = c(.3,.11), col = "gray47", size = 0.7)
# create insets with dummy layers to create separate legend items
d_inset <- tm_shape(ng_nogas_muni) + tm_fill(alpha = 0) +
tm_add_legend(type = "fill", col = "ivory2", labels = "Municipal Utility",
border.col = "white") +
tm_layout(legend.position = c(0.33,0.06), bg.color = NA, frame = FALSE,
legend.text.color = "gray47")
d_inset2 <- tm_shape(ng_nogas_muni) + tm_fill(alpha = 0) +
tm_add_legend(type = "fill", col = "gray88", labels = "No Natural Gas Service",
border.col = "white") +
tm_layout(legend.position = c(0.33,0.025), bg.color = NA, frame = FALSE,
legend.text.color = "gray47")
# create viewports to specify dimensions of insets
vp_inset <- grid::viewport(x = 0.5, y = 0.5, width = 3, height = 1)
vp_inset2 <- grid::viewport(x = 0.5, y = 0.5, width = 3, height = 1)
tmap_save(m1, filename = "Images/pub/m_blkgrpTotal.png",
dpi = 600, height = 4, width = 8, units = "in",
insets_tm = list(d_inset,d_inset2),
insets_vp = list(vp_inset,vp_inset2))
knitr::include_graphics("Images/pub/m_blkgrpTotal.png")
```
```{r mapAllLeaksTR, fig.align='center', fig.cap= "Massachusetts gas leaks per square kilometer by Census Tract, 2019",cache=TRUE}
tractsLeaksAll <- ma_tracts %>%
filter(AllLeaks2019_sqkm > 0)
m2 <- tm_shape(tractsLeaksAll, bbox = ma_state_sf) +
tm_fill(col = "AllLeaks2019_sqkm",
style = "fisher",
palette = "YlOrRd",
title = "Leaks per SqKm",
legend.format = list(digits = 2)) +
tm_shape(ng_nogas_muni) +
tm_fill(col = "GAS_LABEL", palette = c("ivory2","gray88"), title = "",
legend.show = FALSE) +
tm_shape(ma_tracts) + tm_borders(lwd = 0.01, alpha = 0.8) +
tm_shape(ng_service_areas2) + tm_borders(lwd = 0.8, col = "grey68", alpha = 0.7) +
tm_shape(ng_service_labels) +
tm_text("ID", size = 0.6, col = "gray") +
tm_shape(ng_service_labels2) +
tm_text("ID", size = 0.4, col = "gray") +
tm_shape(ng_service_labels3) +
tm_text("ID", size = 0.6, col = "gray", xmod = 2.7, ymod = 0.7) +
# tm_shape(EJlayer) + tm_borders(col = "blue", alpha = 0.7) +
tm_shape(ma_towns_sf_pts) + tm_dots() +
tm_text("NAME", size = 0.4, col = "black",
xmod = 0.7, ymod = 0.2, shadow = TRUE) +
tm_shape(newton) + tm_dots() +
tm_text("NAME", size = 0.4, col = "black",
xmod = -0.7, ymod = 0.2, shadow = TRUE) +
tm_scale_bar(breaks = c(0,25,50), position = c("left","BOTTOM")) +
tm_layout(legend.position = c(0.050,0.15),
title = "Massachusetts Gas Leak Density by Census Tract and Utility Territories, 2019",
inner.margins = c(0.02,0.02,0.09,0.02)) +
tm_credits("BG = Berkshire Gas\nBGC = Blackstone Gas Co.\nCG = Columbia Gas\nEV = Eversource Energy\nLU = Liberty Utilities\nNG = National Grid\nUN = Unitil/Fitchburg Gas", position = c(.3,.11), col = "gray47", size = 0.7)
# create insets with dummy layers to create separate legend items
d_inset <- tm_shape(ng_nogas_muni) + tm_fill(alpha = 0) +
tm_add_legend(type = "fill", col = "ivory2", labels = "Municipal Utility",
border.col = "white") +
tm_layout(legend.position = c(0.33,0.06), bg.color = NA, frame = FALSE,
legend.text.color = "gray47")
d_inset2 <- tm_shape(ng_nogas_muni) + tm_fill(alpha = 0) +
tm_add_legend(type = "fill", col = "gray88", labels = "No Natural Gas Service",
border.col = "white") +
tm_layout(legend.position = c(0.33,0.025), bg.color = NA, frame = FALSE,
legend.text.color = "gray47")
# create viewports to specify dimensions of insets
vp_inset <- grid::viewport(x = 0.5, y = 0.5, width = 3, height = 1)
vp_inset2 <- grid::viewport(x = 0.5, y = 0.5, width = 3, height = 1)
tmap_save(m2, filename = "Images/pub/m_tractTotal.png",
dpi = 600, height = 4, width = 8, units = "in",
insets_tm = list(d_inset,d_inset2),
insets_vp = list(vp_inset,vp_inset2))
knitr::include_graphics("Images/pub/m_tractTotal.png")
```
```{r mapAllLeaksCO, fig.align='center', fig.cap= "Massachusetts gas leaks per square kilometer by municipality, 2019",cache=TRUE}
cosubLeaksAll <- ma_cosub %>%
filter(AllLeaks2019_sqkm > 0)
m3 <- tm_shape(cosubLeaksAll, bbox = ma_state_sf) +
tm_fill(col = "AllLeaks2019_sqkm", style = "fisher", palette = "YlOrRd",
title = "Leaks per SqKm",legend.format = list(digits = 2)) +
tm_shape(ng_nogas_muni) +
tm_fill(col = "GAS_LABEL", palette = c("ivory2","gray88"), title = "",
legend.show = FALSE) +
tm_shape(ma_cosub) + tm_borders(lwd = 0.01, alpha = 0.8) +
tm_shape(ng_service_areas2) + tm_borders(lwd = 0.8, col = "grey68", alpha = 0.7) +
tm_shape(ng_service_labels) +
tm_text("ID", size = 0.6, col = "gray") +
tm_shape(ng_service_labels2) +
tm_text("ID", size = 0.4, col = "gray") +
tm_shape(ng_service_labels3) +
tm_text("ID", size = 0.6, col = "gray", xmod = 2.7, ymod = 0.7) +
# tm_shape(EJlayer) + tm_borders(col = "blue", alpha = 0.7) +
tm_shape(ma_towns_sf_pts) + tm_dots() +
tm_text("NAME", size = 0.4, col = "black",
xmod = 0.7, ymod = 0.2, shadow = TRUE) +
tm_shape(newton) + tm_dots() +
tm_text("NAME", size = 0.4, col = "black",
xmod = -0.7, ymod = 0.2, shadow = TRUE) +
tm_scale_bar(breaks = c(0,25,50), position = c("left","BOTTOM")) +
tm_layout(legend.position = c(0.050,0.15),
title = "Massachusetts Gas Leak Density by Municipality and Utility Territories, 2019",
inner.margins = c(0.02,0.02,0.09,0.02)) +
tm_credits("BG = Berkshire Gas\nBGC = Blackstone Gas Co.\nCG = Columbia Gas\nEV = Eversource Energy\nLU = Liberty Utilities\nNG = National Grid\nUN = Unitil/Fitchburg Gas", position = c(.3,.11), col = "gray47", size = 0.7)
# create insets with dummy layers to create separate legend items
d_inset <- tm_shape(ng_nogas_muni) + tm_fill(alpha = 0) +
tm_add_legend(type = "fill", col = "ivory2", labels = "Municipal Utility",
border.col = "white") +
tm_layout(legend.position = c(0.33,0.06), bg.color = NA, frame = FALSE,
legend.text.color = "gray47")
d_inset2 <- tm_shape(ng_nogas_muni) + tm_fill(alpha = 0) +
tm_add_legend(type = "fill", col = "gray88", labels = "No Natural Gas Service",
border.col = "white") +
tm_layout(legend.position = c(0.33,0.025), bg.color = NA, frame = FALSE,
legend.text.color = "gray47")
# create viewports to specify dimensions of insets
vp_inset <- grid::viewport(x = 0.5, y = 0.5, width = 3, height = 1)
vp_inset2 <- grid::viewport(x = 0.5, y = 0.5, width = 3, height = 1)
tmap_save(m3, filename = "Images/pub/m_cosubTotal.png",
dpi = 600, height = 4, width = 8, units = "in",
insets_tm = list(d_inset,d_inset2),
insets_vp = list(vp_inset,vp_inset2))
knitr::include_graphics("Images/pub/m_cosubTotal.png")
```
```{r tabBGcount, fig.align='center', include=FALSE}
# table of leak count stats by block group
# list of stats to compute across
summary_stats <- list(Min = ~min(., na.rm = T),
Med = ~median(., na.rm = T),
Avg = ~mean(., na.rm = T),
Max = ~max(., na.rm = T))
# table of stats by block group
unrep_blkgrp_cnt <- ma_blkgrps %>%
as.data.frame() %>%
select(starts_with("unrepaired")) %>%
pivot_longer(cols = everything(), names_to = "Class", values_to = "Count") %>%
group_by(Class) %>%
summarize(across(.cols = Count, summary_stats,
.names = "{.fn}U")) %>%
mutate(Class = recode(Class, "unrepaired2019total" = "All",
"unrepaired2019totalC1" = "1",
"unrepaired2019totalC2" = "2",
"unrepaired2019totalC3" = "3")) %>%
arrange(Class)
rep_blkgrp_cnt <- ma_blkgrps %>%
as.data.frame() %>%
select(starts_with("repaired")) %>%
pivot_longer(cols = everything(), names_to = "Class", values_to = "Count") %>%
group_by(Class) %>%
summarize(across(.cols = Count, summary_stats,
.names = "{.fn}R")) %>%
mutate(Class = recode(Class, "repaired2019total" = "All",
"repaired2019totalC1" = "1",
"repaired2019totalC2" = "2",
"repaired2019totalC3" = "3")) %>%
arrange(Class)
all_blkgrp_cnt <- ma_blkgrps %>%
as.data.frame() %>%
select(AllLeaks2019:AllLeaks2019C3) %>%
pivot_longer(cols = everything(), names_to = "Class", values_to = "Count") %>%
group_by(Class) %>%
summarize(across(.cols = Count, summary_stats,
.names = "{.fn}T")) %>%
mutate(Class = recode(Class, "AllLeaks2019" = "All",
"AllLeaks2019C1" = "1",
"AllLeaks2019C2" = "2",
"AllLeaks2019C3" = "3")) %>%
arrange(Class)
# join together
list(unrep_blkgrp_cnt,rep_blkgrp_cnt,all_blkgrp_cnt) %>%
reduce(., left_join, by = "Class") %>%
kable(., longtable = T, booktabs = T,
# format.args = list(big.mark = ','),
caption = "Gas leak counts by class per Census Block Group, 2019",
align = "r",
digits = c(0,0,0,1,0,0,0,1,0,0,0,1),
col.names = c("Class","Min","Med","Avg","Max",
"Min","Med","Avg","Max",
"Min","Med","Avg","Max")) %>%
add_header_above(., c(" ", "Unrepaired Leaks" = 4, "Repaired Leaks" = 4,
"Total Leaks" = 4)) %>%
# row_spec(4, bold = T) %>%
kable_styling(latex_options = c("repeat_header"))
```
```{r calcUtility, include=FALSE}
# create df of counts per utility
unrepairedUSum_df <- unrepaired2019 %>%
as.data.frame() %>%
mutate(Utility = recode(Utility,
"Fitchburg" = "Unitil/Fitchburg Gas",
"Eversource" = "Eversource Energy")) %>%
group_by(Utility) %>%
summarize(Unrepaired = n())
repairedUSum_df <- repaired2019 %>%
as.data.frame() %>%
mutate(Utility = recode(Utility,
"Fitchburg" = "Unitil/Fitchburg Gas",
"Eversource" = "Eversource Energy")) %>%
group_by(Utility) %>%
summarize(Repaired = n())
totalUSum_df <- left_join(unrepairedUSum_df, repairedUSum_df, by = "Utility") %>%
mutate(Total = Unrepaired + Repaired) %>%
bind_rows(summarize(.,
across(where(is.numeric), sum),
across(where(is.character), ~ "Total"))) %>%
mutate(PctUnrepaired = Unrepaired/Total*100,
PctRepaired = Repaired/Total*100,
PctTotal = Total/Total[Utility == "Total"]*100) %>%
select(Utility, Unrepaired, PctUnrepaired, Repaired, PctRepaired, Total, PctTotal)
```
The vast majority of all leaks were located in the eastern half of the state, particularly in the greater Boston region, where most of the population resides, but also within major cities throughout the state. Moreover, most of these leaks (`r totalUSum_df %>% filter(Utility == "National Grid") %>% select(PctTotal) %>% pull() %>% round(.,0)`%) occurred within the service territory of National Grid, which is the largest natural gas utility in the state, serving Boston and surrounding communities (see Figure \@ref(fig:figLeaksUtility)).
```{r tabBGdensity, fig.align='center', include=FALSE}
# table of leak density stats by block group
# list of stats to compute across
summary_stats <- list(Min = ~min(., na.rm = T),
Med = ~median(., na.rm = T),
Avg = ~mean(., na.rm = T),
Max = ~max(., na.rm = T))
# table of stats by block group
unrep_blkgrp_dns <- ma_blkgrps %>%
as.data.frame() %>%
select(starts_with("leaks_sqkm")) %>%
pivot_longer(cols = everything(), names_to = "Class", values_to = "Count") %>%
group_by(Class) %>%
summarize(across(.cols = Count, summary_stats,
.names = "{.fn}U")) %>%
mutate(Class = recode(Class, "leaks_sqkm" = "All",
"leaks_sqkmC1" = "1",
"leaks_sqkmC2" = "2",
"leaks_sqkmC3" = "3")) %>%
arrange(Class)
rep_blkgrp_dns <- ma_blkgrps %>%
as.data.frame() %>%
select(starts_with("REPleaks_sqkm")) %>%
pivot_longer(cols = everything(), names_to = "Class", values_to = "Count") %>%
group_by(Class) %>%
summarize(across(.cols = Count, summary_stats,
.names = "{.fn}R")) %>%
mutate(Class = recode(Class, "REPleaks_sqkm" = "All",
"REPleaks_sqkmC1" = "1",
"REPleaks_sqkmC2" = "2",
"REPleaks_sqkmC3" = "3")) %>%
arrange(Class)
all_blkgrp_dns <- ma_blkgrps %>%
as.data.frame() %>%
select(AllLeaks2019_sqkm:AllLeaks2019C3_sqkm) %>%
pivot_longer(cols = everything(), names_to = "Class", values_to = "Count") %>%
group_by(Class) %>%
summarize(across(.cols = Count, summary_stats,
.names = "{.fn}T")) %>%
mutate(Class = recode(Class, "AllLeaks2019_sqkm" = "All",
"AllLeaks2019C1_sqkm" = "1",
"AllLeaks2019C2_sqkm" = "2",
"AllLeaks2019C3_sqkm" = "3")) %>%
arrange(Class)
# join together
list(unrep_blkgrp_dns,rep_blkgrp_dns,all_blkgrp_dns) %>%
reduce(., left_join, by = "Class") %>%
kable(., longtable = T, booktabs = T,
# format.args = list(big.mark = ','),
caption = "Gas leak density (per sqkm) by class per Census Block Group, 2019",
align = "r",
digits = 2,
col.names = c("Class","Min","Med","Avg","Max",
"Min","Med","Avg","Max",
"Min","Med","Avg","Max")) %>%
add_header_above(., c(" ", "Unrepaired Leaks" = 4, "Repaired Leaks" = 4,
"Total Leaks" = 4)) %>%
# row_spec(4, bold = T) %>%
kable_styling(latex_options = c("repeat_header"))
```
```{r figLeaksUtility, fig.align='center', fig.cap="Frequency of reported repaired and unrepaired leaks by natural gas utility in Massachusetts, 2019"}
# create a stacked bar chart of leaks by utility. shows significant difference in magnitude.
unrepairedUSum_df <- unrepaired2019 %>%
as.data.frame() %>%
mutate(Utility = recode(Utility,
"Fitchburg" = "Unitil/Fitchburg Gas",
"Eversource" = "Eversource Energy")) %>%
group_by(Utility) %>%
summarize(Unrepaired = n())
repairedUSum_df <- repaired2019 %>%
as.data.frame() %>%
mutate(Utility = recode(Utility,
"Fitchburg" = "Unitil/Fitchburg Gas",
"Eversource" = "Eversource Energy")) %>%
group_by(Utility) %>%
summarize(Repaired = n())
totalUSum_df <- left_join(unrepairedUSum_df, repairedUSum_df, by = "Utility") %>%
mutate(Total = Unrepaired + Repaired) %>%
bind_rows(summarize(.,
across(where(is.numeric), sum),
across(where(is.character), ~ "Total"))) %>%
mutate(PctUnrepaired = Unrepaired/Total*100,
PctRepaired = Repaired/Total*100,
PctTotal = Total/Total[Utility == "Total"]*100) %>%
select(Utility, Unrepaired, PctUnrepaired, Repaired, PctRepaired, Total, PctTotal)
totalUSum_df %>%
filter(Utility != "Total") %>%
select(-c(Total, starts_with("Pct"))) %>%
pivot_longer(., cols = c(Unrepaired,Repaired),
names_to = "status", values_to = "leaks") %>%
ggplot(aes(x = reorder(Utility, leaks), y = leaks,
fill = status)) +
geom_bar(position = "stack", stat = "identity") +
scale_fill_manual("legend", values = c("Repaired" = "#7CB5EC",
"Unrepaired" = "#F7A35C")) +
coord_flip() +
theme_minimal() +
theme(legend.title = element_blank(), legend.position = "top") +
scale_y_continuous(labels=function(x) format(x, big.mark = ",", scientific = FALSE)) +
guides(fill = guide_legend(reverse = TRUE)) +
labs(x = NULL,
y = "Reported Leaks",
title = "Reported leaks by utility in 2019 across Massachusetts")
ggsave("Images/pub/LeaksbyUtility.png")
```
## Exposure
### Statewide exposure
Exposure to unrepaired leaks demonstrates consistently strong differences both geographically and demographically. White residents and people over 64 consistently experience below average population-weighted leak densities for all classes or grades of unrepaired leaks. This is the most invariant finding and is unaffected by the scale or unit of analysis, and true in every utility territory except Berkshire Gas in western Massachusetts. Conversely, People of Color (particularly Asians and Blacks), as well as limited-English speaking households, consistently experience higher densities of unrepaired leaks. Moreover, race and English-language ability exhibit more consistent leak exposure disparities than income indicators in every utility territory save for Berkshire Gas.
Figure \@ref(fig:figDotUnrepaired) shows the relative exposure by leak class for unrepaired leaks for each population group at the Census Block Group (square), Census Tract (triangle), and municipality (circle) levels. For all leak classes, White people experience population-weighted mean relative exposures to unrepaired leaks that range from `r round(1-ppLeakDensity_df_co %>% filter(Group == "White") %>% select(wLeaksRR) %>% pull(),2)*100`% (RE `r round(ppLeakDensity_df_co %>% filter(Group == "White") %>% select(wLeaksRR) %>% pull(),2)` at municipality level) to `r round(1-ppLeakDensity_df_bg %>% filter(Group == "White") %>% select(wLeaksRR) %>% pull(),2)*100`% (RE `r round(ppLeakDensity_df_bg %>% filter(Group == "White") %>% select(wLeaksRR) %>% pull(),2)` at Block Group level) below that of the general population. By contrast, Black people experience relative exposures of `r abs(round(1-ppLeakDensity_df_co %>% filter(Group == "Black") %>% select(wLeaksRR) %>% pull(),2))*100`% (RE `r round(ppLeakDensity_df_co %>% filter(Group == "Black") %>% select(wLeaksRR) %>% pull(),2)` at municipality level) to `r abs(round(1-ppLeakDensity_df_bg %>% filter(Group == "Black") %>% select(wLeaksRR) %>% pull(),2))*100`% (RE `r round(ppLeakDensity_df_bg %>% filter(Group == "Black") %>% select(wLeaksRR) %>% pull(),2)` at Block Group level) above that of the general population. The differences are starker for potentially more hazardous Class 1 and Class 2 leaks.
For Class 1 unrepaired leak densities, Whites have a relative exposure of approximately `r round(1-ppLeakDensity_df_co %>% filter(Group == "White") %>% select(wLeaksRRC1) %>% pull(),2)*100`% (RE `r round(ppLeakDensity_df_co %>% filter(Group == "White") %>% select(wLeaksRRC1) %>% pull(),2)`) below that of the general population at all scales of analysis. By comparison, Blacks have exposures of `r abs(round(1-ppLeakDensity_df_bg %>% filter(Group == "Black") %>% select(wLeaksRRC1) %>% pull(),2))*100`% (RE `r round(ppLeakDensity_df_bg %>% filter(Group == "Black") %>% select(wLeaksRRC1) %>% pull(),2)` at Block Group level) to `r abs(round(1-ppLeakDensity_df_co %>% filter(Group == "Black") %>% select(wLeaksRRC1) %>% pull(),2))*100`% (`r round(ppLeakDensity_df_co %>% filter(Group == "Black") %>% select(wLeaksRRC1) %>% pull(),2)` at municipality level) above that of the general population. For Class 2 unrepaired leak densities, Whites have a relative exposure of `r round(1-ppLeakDensity_df_co %>% filter(Group == "White") %>% select(wLeaksRRC2) %>% pull(),2)*100`% (RE `r round(ppLeakDensity_df_co %>% filter(Group == "White") %>% select(wLeaksRRC2) %>% pull(),2)` at municipality level) to `r round(1-ppLeakDensity_df_tr %>% filter(Group == "White") %>% select(wLeaksRRC2) %>% pull(),2)*100`% (`r round(ppLeakDensity_df_tr %>% filter(Group == "White") %>% select(wLeaksRRC2) %>% pull(),2)` at Tract level) below that of the general population. Blacks have exposures of `r abs(round(1-ppLeakDensity_df_co %>% filter(Group == "Black") %>% select(wLeaksRRC2) %>% pull(),2))*100`% (RE `r round(ppLeakDensity_df_co %>% filter(Group == "Black") %>% select(wLeaksRRC2) %>% pull(),2)` at municipality level) to `r abs(round(1-ppLeakDensity_df_tr %>% filter(Group == "Black") %>% select(wLeaksRRC2) %>% pull(),2))*100`% (`r round(ppLeakDensity_df_tr %>% filter(Group == "Black") %>% select(wLeaksRRC2) %>% pull(),2)` at Tract level) above that of the general population. Residents in state-designated, limited English environmental justice communities (MA Limited English HH) exhibit the greatest relative exposures for higher hazard leaks; over `r abs(round(1-ppLeakDensity_df_bg %>% filter(Group == "MA_ENGLISH") %>% select(wLeaksRRC2) %>% pull(),0))*100`% above that of the general population.
Differences in relative exposure vary only slightly by the unit or scale of analysis. In general, the differences in relative exposure are most pronounced at the Census Block Group level (smallest geographic unit of analysis) and are lowest at the municipality level (largest geographic unit of analysis). For Class 2 leaks, however, Block Group-level differences fall in between those of the Tract and municipality level analyses. Relative exposures for Class 1 and Class 2 leaks exhibit the largest spread across the scales of analysis. However, Class 3 leaks, which account for the majority of unrepaired leaks, show considerable overlap or agreement between the scales of analysis.
```{r figDotUnrepaired, fig.align='center', fig.cap="Relative exposures to population-weighted mean unrepaired gas leak density at Census Block Group, Census Tract, and municipality scales"}
# dot graph of relative exposure for unrepaired leak density around zero line
cols <- c("#F7A35C", "#7CB5EC", "gray30")
shps <- c(0,2,1)
# create a consistent factor order to keep groups in a consistent order across all graphs
group_orderBG <- ppLeakDensity_df_bg %>%
arrange(desc(wLeaksRR)) %>%
select(Group) %>%
pull()
group_orderTR <- ppLeakDensity_df_tr %>%
arrange(wLeaksRR) %>%
select(Group) %>%
pull()
group_orderCO <- ppLeakDensity_df_co %>%
arrange(wLeaksRR) %>%
select(Group) %>%
pull()
# Set up for dot graph to show all three scales
ppLeakDensity_df_bg2 <- ppLeakDensity_df_bg %>%
mutate(Group = factor(Group, levels = group_orderBG)) %>%
pivot_longer(wLeaksRR:wLeaksRRC3,
names_to = "leakClass", values_to = "leakDensityBG") %>%
# filter(!Group %in% c("MA_ENGLISH","MA_MINORITY21","MA_INCOME21")) %>%
mutate(Group = recode(Group, "MA_ENGLISH" = "MA Limited English HH",
"MA_MINORITY21" = "MA Minority",
"MA_INCOME21" = "MA Low Income")) %>%
mutate(leakClass = recode(leakClass, "wLeaksRR" = paste0("All Leaks"," (n = ",formatC(nrow(unrepaired2019),big.mark = ","),")"),
"wLeaksRRC1" = paste0("Class 1 Leaks"," (n = ",formatC(nrow(filter(unrepaired2019,Class == "1")),big.mark = ","),")"),
"wLeaksRRC2" = paste0("Class 2 Leaks"," (n = ",formatC(nrow(filter(unrepaired2019,Class == "2")),big.mark = ","),")"),