library(tidyverse)
library(naniar)
#install.packages(c('s2', 'units','rJava','raster', 'sf','terra', 'sftime','stars', 'gstat','RNetCDF', 'ncmeta', 'areal', 'ncdfgeom', 'leafem', 'leafgl', 'leaflegend', 'leaflet', 'leafsync', 'maptiles', 'tmaptools', 'tmap', 'lwgeom', 'leafpop','satellite', 'mapview'), repos = "https://cloud.r-project.org", dependencies = TRUE)
library(sf)
#library(s2)
#library(units)
Data Import
BMF file from: https://nccsdata.s3.amazonaws.com/harmonized/bmf/unified/MD_BMF_V1.1.csv
Neighborhood csv file from: https://data.baltimorecity.gov/datasets/baltimore::neighborhood-statistical-area-nsa-boundaries/about
BMF <- read_csv("data/MD_BMF_V1.1.csv")
## Rows: 73768 Columns: 49
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (22): EIN2, NTEE_IRS, NTEE_NCCS, NTEEV2, NCCS_LEVEL_1, NCCS_LEVEL_2, NCC...
## dbl (27): EIN, F990_TOTAL_REVENUE_RECENT, F990_TOTAL_INCOME_RECENT, F990_TOT...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
neighborhoods <- read_csv("data/Neighborhood_Statistical_Area_(NSA)_Boundaries.csv")
## Rows: 279 Columns: 60
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): Name
## dbl (59): OBJECTID, Population, White, Blk_AfAm, AmInd_AkNa, Asian, NatHaw_P...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Check for missing data
BMF_geo <- BMF %>% dplyr::select(EIN, LATITUDE, LONGITUDE)
any(is.na(BMF_geo$LATITUDE)) # no missing location info
## [1] FALSE
any(is.na(BMF_geo$LONGITUDE))
## [1] FALSE
Limit to just Baltimore
Based on coordinates…
#CRS <- st_crs(neighborhood_shape$geometry) # get class sf version of coordinates
BMF_sf <- st_as_sf(BMF, coords = c('LONGITUDE', 'LATITUDE'), crs = st_crs(4326)) %>% st_set_crs(4326) # Use LONGITUDE and LATITUDE columns and convert to sf object (with a geometry column), use coordinate reference system 4326
BMF_trans <- st_transform(BMF_sf, 2163) #EPSG:2163, convert lat and long to NAD27 / US National Atlas Equal Area for the org data
## Warning in CPL_crs_from_input(x): GDAL Message 1: CRS EPSG:2163 is deprecated.
## Its non-deprecated replacement EPSG:9311 will be used instead. To use the
## original CRS, set the OSR_USE_NON_DEPRECATED configuration option to NO.
neighborhood_tt <- st_transform(neighborhood_shape$geometry, 2163)# convert Baltimore shape file to NAD27 / US National Atlas Equal Area coordinate reference system
Look for the intersection of orgs with locations within Baltimore
# Make a new column for each org row about if the location is located within the Baltimore shape outline
intersection <- BMF_sf %>% mutate(
intersection = as.integer(st_intersects(BMF_trans, neighborhood_tt )))
# filter for just data within Baltimore dropping other MD orgs
in_balt <- intersection %>% filter(!is.na(intersection)) # just Baltimore locations
Check that it worked
Checking that it worked using this image: https://commons.wikimedia.org/wiki/File:Baltimore_neighborhoods_map.png

in_balt[1,]$intersection # row for intersection
## [1] 108
## [1] 2190718
in_balt[1,]$ORG_ADDR_FULL # this looks like downtown when you look it up
## [1] "225 N CHARLES ST,BALT,MD,21201"
# how does this look in the neighborhood file?
neighborhood_shape[in_balt[1,]$intersection,]$Name # neighborhood name
## [1] "Downtown"
#Looks like this is in that location
in_balt[43,]$ORG_ADDR_FULL
## [1] "901 S BOND ST STE 400,BALTIMORE,MD,21231-3340"
neighborhood_shape[in_balt[43,]$intersection,]$Name # neighborhood name
## [1] "Fells Point"
#Looks like this is in that location
in_balt[58,]$ORG_ADDR_FULL
## [1] "5114 WINDSOR MILL RD,BALTIMORE,MD,21207"
neighborhood_shape[in_balt[58,]$intersection,]$Name # neighborhood name
## [1] "Wakefield"
#Looks like this is in that location
in_balt[65,]$ORG_ADDR_FULL
## [1] "2700 LIGHTHOUSE POINT EAST,BALTIMORE,MD,21224"
neighborhood_shape[in_balt[65,]$intersection,]$Name # neighborhood name
## [1] "Canton"
#Looks like this is in that location
in_balt[100,]$ORG_ADDR_FULL
## [1] "2404 PENNSYLVANIA AVE 2ND FLR,BALTIMORE,MD,21217-1722"
neighborhood_shape[in_balt[100,]$intersection,]$Name # neighborhood name
## [1] "Penn North"
#Looks like this is in that location
Combining it all together
Want the org info, and neighborhood info and shape information
together to enable making maps later.
neighborhood_shape <-as_tibble(neighborhood_shape) # convert to tibble
neighborhood_shape<-neighborhood_shape %>% mutate(id = row_number()) # add row number column
org_data <-left_join(in_balt, neighborhood_shape, by = c("intersection" = "id")) # look for what row numbers align with the shape file
# save neighborhood R file and org data with neighborhood info
write_rds(neighborhood_shape, file = "data/processed/neighborhood_shape_data.rds")
write_rds(org_data, file = "data/processed/org_data.rds")
CmBgYHtyLCBtZXNzYWdlPSBGQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkobmFuaWFyKQojaW5zdGFsbC5wYWNrYWdlcyhjKCdzMicsICd1bml0cycsJ3JKYXZhJywncmFzdGVyJywgJ3NmJywndGVycmEnLCAnc2Z0aW1lJywnc3RhcnMnLCAnZ3N0YXQnLCdSTmV0Q0RGJywgJ25jbWV0YScsICdhcmVhbCcsICduY2RmZ2VvbScsICdsZWFmZW0nLCAnbGVhZmdsJywgJ2xlYWZsZWdlbmQnLCAnbGVhZmxldCcsICdsZWFmc3luYycsICdtYXB0aWxlcycsICd0bWFwdG9vbHMnLCAndG1hcCcsICdsd2dlb20nLCAnbGVhZnBvcCcsJ3NhdGVsbGl0ZScsICdtYXB2aWV3JyksIHJlcG9zID0gImh0dHBzOi8vY2xvdWQuci1wcm9qZWN0Lm9yZyIsIGRlcGVuZGVuY2llcyA9IFRSVUUpCmxpYnJhcnkoc2YpCiNsaWJyYXJ5KHMyKQojbGlicmFyeSh1bml0cykKYGBgCgojIERhdGEgSW1wb3J0CkJNRiBmaWxlIGZyb206Cmh0dHBzOi8vbmNjc2RhdGEuczMuYW1hem9uYXdzLmNvbS9oYXJtb25pemVkL2JtZi91bmlmaWVkL01EX0JNRl9WMS4xLmNzdiAKTmVpZ2hib3Job29kIGNzdiBmaWxlIGZyb206IGh0dHBzOi8vZGF0YS5iYWx0aW1vcmVjaXR5Lmdvdi9kYXRhc2V0cy9iYWx0aW1vcmU6Om5laWdoYm9yaG9vZC1zdGF0aXN0aWNhbC1hcmVhLW5zYS1ib3VuZGFyaWVzL2Fib3V0IAoKYGBge3J9CkJNRiA8LSByZWFkX2NzdigiZGF0YS9NRF9CTUZfVjEuMS5jc3YiKQpuZWlnaGJvcmhvb2RzIDwtIHJlYWRfY3N2KCJkYXRhL05laWdoYm9yaG9vZF9TdGF0aXN0aWNhbF9BcmVhXyhOU0EpX0JvdW5kYXJpZXMuY3N2IikKYGBgCgojIEdldCBsYXQgYW5kIGxvbmcgZm9yIHNoYXBlIGZpbGUKClNoYXBlIGZpbGUgZnJvbTogaHR0cHM6Ly9kYXRhLmJhbHRpbW9yZWNpdHkuZ292L2RhdGFzZXRzL2JhbHRpbW9yZTo6bmVpZ2hib3Job29kLXN0YXRpc3RpY2FsLWFyZWEtbnNhLWJvdW5kYXJpZXMvYWJvdXQKCmh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzY2MzgxNzk1L2NoZWNrLXdoZXRoZXItcG9pbnQtY29vcmRpbmF0ZS1saWVzLXdpdGhpbi1wb2x5Z29uCmh0dHBzOi8vd3d3LnN0YXRzaWxrLmNvbS9tYXBzL2NvbnZlcnQtZXNyaS1zaGFwZWZpbGUtbWFwLWdlb2pzb24tZm9ybWF0CgpgYGB7cn0KbmVpZ2hib3Job29kX3NoYXBlIDwtc3RfcmVhZCgiZGF0YS9OZWlnaGJvcmhvb2RfU3RhdGlzdGljYWxfQXJlYV8oTlNBKV9Cb3VuZGFyaWVzL05laWdoYm9yaG9vZF9TdGF0aXN0aWNhbF9BcmVhXyhOU0EpX0JvdW5kYXJpZXMuc2hwIikKCmBgYAoKCiMgQ2hlY2sgZm9yIG1pc3NpbmcgZGF0YQoKYGBge3J9CkJNRl9nZW8gPC0gQk1GICU+JSBkcGx5cjo6c2VsZWN0KEVJTiwgTEFUSVRVREUsIExPTkdJVFVERSkKYW55KGlzLm5hKEJNRl9nZW8kTEFUSVRVREUpKSAjIG5vIG1pc3NpbmcgbG9jYXRpb24gaW5mbwphbnkoaXMubmEoQk1GX2dlbyRMT05HSVRVREUpKQpgYGAKCgojIExpbWl0IHRvIGp1c3QgQmFsdGltb3JlCgpCYXNlZCBvbiBjb29yZGluYXRlcy4uLgoKYGBge3J9CiNDUlMgPC0gc3RfY3JzKG5laWdoYm9yaG9vZF9zaGFwZSRnZW9tZXRyeSkgIyBnZXQgY2xhc3Mgc2YgdmVyc2lvbiBvZiBjb29yZGluYXRlcwpCTUZfc2YgPC0gc3RfYXNfc2YoQk1GLCBjb29yZHMgPSBjKCdMT05HSVRVREUnLCAnTEFUSVRVREUnKSwgY3JzID0gc3RfY3JzKDQzMjYpKSAlPiUgc3Rfc2V0X2Nycyg0MzI2KSAjIFVzZSBMT05HSVRVREUgYW5kIExBVElUVURFIGNvbHVtbnMgYW5kIGNvbnZlcnQgdG8gc2Ygb2JqZWN0ICh3aXRoIGEgZ2VvbWV0cnkgY29sdW1uKSwgdXNlIGNvb3JkaW5hdGUgcmVmZXJlbmNlIHN5c3RlbSA0MzI2CkJNRl90cmFucyA8LSBzdF90cmFuc2Zvcm0oQk1GX3NmLCAyMTYzKSAjRVBTRzoyMTYzLCBjb252ZXJ0IGxhdCBhbmQgbG9uZyB0byBOQUQyNyAvIFVTIE5hdGlvbmFsIEF0bGFzIEVxdWFsIEFyZWEgZm9yIHRoZSBvcmcgZGF0YQpuZWlnaGJvcmhvb2RfdHQgPC0gc3RfdHJhbnNmb3JtKG5laWdoYm9yaG9vZF9zaGFwZSRnZW9tZXRyeSwgMjE2MykjIGNvbnZlcnQgQmFsdGltb3JlICBzaGFwZSBmaWxlIHRvIE5BRDI3IC8gVVMgTmF0aW9uYWwgQXRsYXMgRXF1YWwgQXJlYSBjb29yZGluYXRlIHJlZmVyZW5jZSBzeXN0ZW0KYGBgCgpMb29rIGZvciB0aGUgaW50ZXJzZWN0aW9uIG9mIG9yZ3Mgd2l0aCBsb2NhdGlvbnMgd2l0aGluIEJhbHRpbW9yZQoKYGBge3J9CiMgTWFrZSBhIG5ldyBjb2x1bW4gZm9yIGVhY2ggb3JnIHJvdyBhYm91dCBpZiB0aGUgbG9jYXRpb24gaXMgbG9jYXRlZCB3aXRoaW4gdGhlIEJhbHRpbW9yZSBzaGFwZSBvdXRsaW5lCmludGVyc2VjdGlvbiA8LSBCTUZfc2YgJT4lIG11dGF0ZSgKICBpbnRlcnNlY3Rpb24gPSBhcy5pbnRlZ2VyKHN0X2ludGVyc2VjdHMoQk1GX3RyYW5zLCBuZWlnaGJvcmhvb2RfdHQgKSkpCgojIGZpbHRlciBmb3IganVzdCBkYXRhIHdpdGhpbiBCYWx0aW1vcmUgZHJvcHBpbmcgb3RoZXIgTUQgb3Jncwppbl9iYWx0IDwtIGludGVyc2VjdGlvbiAlPiUgZmlsdGVyKCFpcy5uYShpbnRlcnNlY3Rpb24pKSAjIGp1c3QgQmFsdGltb3JlIGxvY2F0aW9ucwpgYGAKCgojIENoZWNrIHRoYXQgaXQgd29ya2VkCgoKQ2hlY2tpbmcgdGhhdCBpdCB3b3JrZWQgdXNpbmcgdGhpcyBpbWFnZTogaHR0cHM6Ly9jb21tb25zLndpa2ltZWRpYS5vcmcvd2lraS9GaWxlOkJhbHRpbW9yZV9uZWlnaGJvcmhvb2RzX21hcC5wbmcKCgpgYGB7ciBpbmNsdWRlLWltYWdlLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjQwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vdXBsb2FkLndpa2ltZWRpYS5vcmcvd2lraXBlZGlhL2NvbW1vbnMvNS81Ny9CYWx0aW1vcmVfbmVpZ2hib3Job29kc19tYXAucG5nIikKYGBgCgoKCmBgYHtyfQppbl9iYWx0WzEsXSRpbnRlcnNlY3Rpb24gIyByb3cgZm9yIGludGVyc2VjdGlvbgppbl9iYWx0WzEsXSRFSU4gIyBvcmcgaWQKaW5fYmFsdFsxLF0kT1JHX0FERFJfRlVMTCAjIHRoaXMgbG9va3MgbGlrZSBkb3dudG93biB3aGVuIHlvdSBsb29rIGl0IHVwCgojIGhvdyBkb2VzIHRoaXMgbG9vayBpbiB0aGUgbmVpZ2hib3Job29kIGZpbGU/Cm5laWdoYm9yaG9vZF9zaGFwZVtpbl9iYWx0WzEsXSRpbnRlcnNlY3Rpb24sXSROYW1lICMgbmVpZ2hib3Job29kIG5hbWUKCiNMb29rcyBsaWtlIHRoaXMgaXMgaW4gdGhhdCBsb2NhdGlvbgoKaW5fYmFsdFs0MyxdJE9SR19BRERSX0ZVTEwgCm5laWdoYm9yaG9vZF9zaGFwZVtpbl9iYWx0WzQzLF0kaW50ZXJzZWN0aW9uLF0kTmFtZSAjIG5laWdoYm9yaG9vZCBuYW1lCiNMb29rcyBsaWtlIHRoaXMgaXMgaW4gdGhhdCBsb2NhdGlvbgoKaW5fYmFsdFs1OCxdJE9SR19BRERSX0ZVTEwgCm5laWdoYm9yaG9vZF9zaGFwZVtpbl9iYWx0WzU4LF0kaW50ZXJzZWN0aW9uLF0kTmFtZSAjIG5laWdoYm9yaG9vZCBuYW1lCiNMb29rcyBsaWtlIHRoaXMgaXMgaW4gdGhhdCBsb2NhdGlvbgoKaW5fYmFsdFs2NSxdJE9SR19BRERSX0ZVTEwKbmVpZ2hib3Job29kX3NoYXBlW2luX2JhbHRbNjUsXSRpbnRlcnNlY3Rpb24sXSROYW1lICMgbmVpZ2hib3Job29kIG5hbWUKI0xvb2tzIGxpa2UgdGhpcyBpcyBpbiB0aGF0IGxvY2F0aW9uCgppbl9iYWx0WzEwMCxdJE9SR19BRERSX0ZVTEwKbmVpZ2hib3Job29kX3NoYXBlW2luX2JhbHRbMTAwLF0kaW50ZXJzZWN0aW9uLF0kTmFtZSAjIG5laWdoYm9yaG9vZCBuYW1lCiNMb29rcyBsaWtlIHRoaXMgaXMgaW4gdGhhdCBsb2NhdGlvbgoKYGBgCgoKIyBDb21iaW5pbmcgaXQgYWxsIHRvZ2V0aGVyIAoKV2FudCB0aGUgb3JnIGluZm8sIGFuZCBuZWlnaGJvcmhvb2QgaW5mbyBhbmQgc2hhcGUgaW5mb3JtYXRpb24gdG9nZXRoZXIgdG8gZW5hYmxlIG1ha2luZyBtYXBzIGxhdGVyLgoKYGBge3J9Cm5laWdoYm9yaG9vZF9zaGFwZSA8LWFzX3RpYmJsZShuZWlnaGJvcmhvb2Rfc2hhcGUpICMgY29udmVydCB0byB0aWJibGUKbmVpZ2hib3Job29kX3NoYXBlPC1uZWlnaGJvcmhvb2Rfc2hhcGUgJT4lICBtdXRhdGUoaWQgPSByb3dfbnVtYmVyKCkpICMgYWRkIHJvdyBudW1iZXIgY29sdW1uCm9yZ19kYXRhIDwtbGVmdF9qb2luKGluX2JhbHQsIG5laWdoYm9yaG9vZF9zaGFwZSwgYnkgPSBjKCJpbnRlcnNlY3Rpb24iID0gImlkIikpICMgbG9vayBmb3Igd2hhdCByb3cgbnVtYmVycyBhbGlnbiB3aXRoIHRoZSBzaGFwZSBmaWxlCgojIHNhdmUgbmVpZ2hib3Job29kIFIgZmlsZSBhbmQgb3JnIGRhdGEgd2l0aCBuZWlnaGJvcmhvb2QgaW5mbwp3cml0ZV9yZHMobmVpZ2hib3Job29kX3NoYXBlLCBmaWxlID0gImRhdGEvcHJvY2Vzc2VkL25laWdoYm9yaG9vZF9zaGFwZV9kYXRhLnJkcyIpCndyaXRlX3JkcyhvcmdfZGF0YSwgZmlsZSA9ICJkYXRhL3Byb2Nlc3NlZC9vcmdfZGF0YS5yZHMiKQoKYGBgCg==