-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdataeditor.py
138 lines (113 loc) · 3.19 KB
/
dataeditor.py
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
import json
import os
import geojson
from census import Census
from us import states
# -- Config
COUNTIES = {
"Suffolk": "025", # Boston
"Middlesex": "017", # Somerville/Cambridge
"Essex": "009" # The stuff in the north
}
VARIABLES = {
'Tract Name': 'NAME',
'Population': 'B01003_001E',
'Median Household Income': 'B19013_001E',
'Median Contract Rent': 'B25058_001E',
'Median Home Value': 'B25077_001E',
# 'Employed': 'B23025_004E',
# 'Unemployed': 'B23025_005E',
# 'Commute Time (minutes)': 'B08136_001E', # Not included in the 2010 ACS5 data
'Impoverished Pop': 'B17001_002E',
}
GEOJSON_VARS = {
'Housing Units': 'HU100_RE',
}
ALIASES = {value: key for key, value in VARIABLES.items()}
# -- Definitions
def loadAPIKey(name):
with open("./private.json", 'r') as private:
apiKey = json.load(private)['API-keys'][name]
return apiKey
class Data:
def __init__(self, load=False, filepath="data/data.json"):
self.filepath = filepath
if load and os.path.isfile(filepath):
with open(filepath, "r") as datafile:
self.data = json.load(datafile)
else:
self.data = {}
def alias(self, datum, aliases=ALIASES):
'''
Given a dictionary with census encoded keys
(eg. B01003_001E), replaces those keys with
a human readable key (eg. 'Population') based
on the `aliases` argument. The `aliases` argument
should be a dictionary of `census code: alias`
key/value pairs.
'''
aliasedDatum = {}
for key, value in datum.items():
if key in ALIASES:
aliasedDatum[aliases[key]] = value
else:
aliasedDatum[key] = value
return aliasedDatum
def update(self, tractID, newdata, addNew=False):
'''
Add the keys and values from `newdata` to the
data object, aliasing the key names.
Strictly updates (does not add a new item to the
data object) unless the `addNew` parameter is
set to `True`.
'''
aliasedData = self.alias(newdata)
if tractID in self.data:
for key, value in aliasedData.items():
self.data[tractID][key] = str(value)
elif addNew:
self.data[tractID] = aliasedData
def save(self):
'''
Saves the data to the data file.
'''
listdata = self.data.values()
with open(self.filepath, "w") as datafile:
json.dump(
listdata,
datafile,
sort_keys=True,
indent=2,
separators=(',', ": ")
)
# -- Running Code
if __name__ == "__main__":
YEAR = 2013;
c = Census(loadAPIKey('census'));
data = Data(filepath="data/{}.json".format(YEAR))
# Pull census data to create the data file
for county in COUNTIES.keys():
tractdata = c.acs5.state_county_tract(
VARIABLES.values(),
states.MA.fips,
COUNTIES[county],
Census.ALL,
year=str(YEAR)
)
for tractdatum in tractdata:
data.update(tractdatum['tract'], tractdatum, True)
# Augment with data loaded from downloaded geojson
with open('data/geodata.geojson', 'r') as geodata:
geofeatures = geojson.load(geodata)['features']
for tract in geofeatures:
tractID = tract['properties']['TRACTCE10']
longitude, latitude = tract['geometry']['coordinates']
data.update(tractID, {
'Latitude': latitude,
'Longitude': longitude
})
for propname, prop in GEOJSON_VARS.items():
data.update(tractID, {
propname: tract['properties'][prop]
})
data.save()