cassiebuhler commited on
Commit
a47ab28
·
1 Parent(s): cae0459

cleaning up code

Browse files
Files changed (2) hide show
  1. app.py +127 -241
  2. preprocess.ipynb +9 -124
app.py CHANGED
@@ -1,10 +1,15 @@
1
  import ibis
2
  from ibis import _
3
- import streamlit as st
4
 
 
5
  import altair as alt
6
-
7
-
 
 
 
 
 
8
 
9
  st.set_page_config(layout="wide",
10
  page_title="TPL LandVote",
@@ -17,32 +22,21 @@ An experimental platform for visualizing data on ballot measures for conservatio
17
 
18
  '''
19
 
20
- dark_orange = 'rgba(171, 86, 1, 1)' # dark orange - min value
21
- light_orange = 'rgba(243, 211, 177, 1)' # light orange
22
- grey = 'rgba(211, 211, 211, 1)' # grey
23
- light_green = 'rgba(195, 219, 195, 1)' # light green
24
- dark_green = 'rgba(65, 125, 65, 1)' # dark green - max value
 
 
 
 
25
 
26
- dem_blue = "#1b46c2"
27
- rep_red = "#E81B23"
28
-
29
- ## Chatbot
30
- import os
31
- import pandas as pd
32
- import matplotlib.pyplot as plt
33
- from pandasai.llm.openai import OpenAI
34
- from pandasai import Agent
35
- from pandasai.responses.streamlit_response import StreamlitResponse
36
 
 
37
  llm = OpenAI(api_token=st.secrets["OPENAI_API_KEY"])
38
  df1 = pd.read_csv("data.csv")
39
-
40
- agent = Agent(
41
- [df1],
42
- config={"verbose": True, "response_parser": StreamlitResponse, "llm": llm},
43
- )
44
-
45
-
46
 
47
  with st.sidebar:
48
 
@@ -67,178 +61,132 @@ with st.sidebar:
67
  st.image(im)
68
  os.remove('exports/charts/temp_chart.png')
69
  st.write(resp)
70
-
71
 
 
72
 
73
-
74
- # year = st.slider("Select a year", min_value=1988, max_value=2024, value=2022, step=2)
75
- year = st.slider("Select a year", min_value=1988, max_value=2024, value=2022, step=1)
76
 
 
 
77
 
78
- url = "https://huggingface.co/datasets/boettiger-lab/landvote/resolve/main/votes.pmtiles"
79
- parties = "https://huggingface.co/datasets/boettiger-lab/landvote/resolve/main/votes.parquet"
80
-
81
  con = ibis.duckdb.connect(extensions=["spatial"])
82
-
83
  party = (con
84
- .read_parquet(parties)
85
- .cast({"geometry": "geometry"})
86
- )
87
-
88
- def get_passes(party):
89
- df = (party
90
- .filter(_.year >= 2000)
91
- .group_by("year", "party")
92
- .aggregate(total=_.count(),
93
- passes = (_.Status.isin(["Pass", "Pass*"]).sum())
94
- )
95
- .mutate(
96
- percent_passed=(_.passes / _.total).round(2),
97
- color=ibis.case()
98
- .when(_.party == "DEMOCRAT", ibis.literal("#2e4a93"))
99
- .else_(ibis.literal("#E81B23"))
100
- .end()
101
  )
102
- )
103
-
104
- df = df.to_pandas()
105
- return df
106
 
107
 
108
- def percent_chart(df_passes):
109
- alt.themes.enable('fivethirtyeight')
 
 
 
 
 
110
 
111
- chart = alt.Chart(df_passes).mark_line(strokeWidth=3).encode(
112
- x=alt.X('year:N', title='Year'),
113
- y=alt.Y('percent_passed:Q', title='Percent Passed'),
114
- color=alt.Color('party:N', # Map 'party' to color
115
- scale=alt.Scale(domain=["DEMOCRAT", "REPUBLICAN"],
116
- range=["#1b46c2", "#E81B23"]),
117
- legend=alt.Legend(title="Party")
118
- )
119
  ).properties(
120
- title='% of Measures Passed'
121
  )
122
-
123
- st.altair_chart(chart, use_container_width=True)
 
 
 
 
 
 
 
 
124
 
125
 
 
126
  def funding_chart(party):
127
- df = (party
128
- .mutate(amount=_.amount.replace('$', '').replace(',', '').cast('float64'))
129
- .filter(_.Status.isin(["Pass", "Pass*"]))
130
- .group_by("year")
131
- .aggregate(total_funding=_.amount.sum())
132
- .order_by("year")
133
- .mutate(cumulative_funding=_.total_funding.cumsum()/1e9)
134
- .execute()
135
- )
136
-
137
- chart = alt.Chart(df).mark_line(strokeWidth=3).encode(
138
- x=alt.X('year:N', title='Year'),
139
- y=alt.Y('cumulative_funding:Q', title='Billions of Dollars'),
140
- ).properties(
141
- title='Cumulative Funding'
142
- )
143
 
144
- st.altair_chart(chart, use_container_width=True)
145
-
146
 
 
147
  paint_fill = {
148
- "fill-color": [
149
- "case",
150
- # if passed, color green
151
- ["==", ["get", "Status"], "Pass"],
152
- [
153
- "interpolate", ["linear"], [
154
- "to-number", ["slice", ["get", "yes"], 0, -1] # convert 'yes' string to number
155
- ],
156
- 50, grey,
157
- 55, light_green, # higher yes % -> darker green
158
- 100, dark_green # 100 is the max of data
159
- ],
160
- # if failed, color orange
161
- ["==", ["get", "Status"], "Fail"],
162
- [
163
- "interpolate", ["linear"], [
164
- "to-number", ["slice", ["get", "yes"], 0, -1] # convert 'yes' string to number
165
- ],
166
- 0, dark_orange, # higher yes % -> lighter orange
167
- 50, light_orange,
168
- 67, grey # 67 is the max of data.
169
- ],
170
- grey # if no match
171
- ]
172
- }
173
-
174
 
 
175
  paint_extrusion = {
176
- "fill-extrusion-color": [
177
- "case",
178
- # if passed, color green
179
- ["==", ["get", "Status"], "Pass"],
180
- [
181
- "interpolate", ["linear"], [
182
- "to-number", ["slice", ["get", "yes"], 0, -1] # convert 'yes' string to number
183
- ],
184
- 50, grey,
185
- 55, light_green, # higher yes % -> darker green
186
- 100, dark_green # 100 is the max of data
187
- ],
188
- # if failed, color orange
189
- ["==", ["get", "Status"], "Fail"],
190
- [
191
- "interpolate", ["linear"], [
192
- "to-number", ["slice", ["get", "yes"], 0, -1] # convert 'yes' string to number
193
- ],
194
- 0, dark_orange, # higher yes % -> lighter orange
195
- 50, light_orange,
196
- 67, grey # 67 is the max of data.
197
- ],
198
- grey # if no match
199
- ],
200
- "fill-extrusion-height": ["*", ["get", "log_amount"], 5000],
201
- }
202
 
203
 
 
 
204
  def get_style_status(jurisdiction):
205
  if jurisdiction == "State":
206
  name = "state"
207
  label = "states"
208
  paint_type = paint_fill
209
  layer_type = "fill"
210
-
211
  elif jurisdiction == "County":
212
  name = "county"
213
  label = "counties"
214
  paint_type = paint_extrusion
215
  layer_type = "fill-extrusion"
216
-
217
- else:
218
  name = "municipal"
219
  label = "cities"
220
  paint_type = paint_extrusion
221
  layer_type = "fill-extrusion"
222
 
223
- style = {
224
  "layers": [
225
  {
226
  "id": label,
227
  "source": name,
228
  "source-layer": name,
229
  "type": layer_type,
230
- "filter": [
231
- "==",
232
- ["get", "year"],
233
- year,
234
- ],
235
  "paint": paint_type
236
- },
237
- ],
238
  }
239
- return style
240
 
241
 
 
242
  def get_style_party(jurisdiction):
243
  if jurisdiction == "State":
244
  name = "state"
@@ -246,119 +194,57 @@ def get_style_party(jurisdiction):
246
  elif jurisdiction == "County":
247
  name = "county"
248
  label = "counties"
249
-
250
- else:
251
  name = "municipal"
252
  label = "cities"
253
 
254
-
255
- style_party = {
256
  "layers": [
257
  {
258
- "id": label,
259
  "source": name,
260
  "source-layer": name,
261
  "type": "fill",
262
  "filter": [
263
- "==",
264
- ["get", "year"],
265
- year,
266
  ],
267
  "paint": {
268
- "fill-color":
269
- {
270
- 'property': 'party',
271
- 'type': 'categorical',
272
- 'stops': [
273
- ["DEMOCRAT", dem_blue],
274
- ["REPUBLICAN", rep_red],
275
- ]
276
  }
277
  }
278
- },
279
- ],
280
  }
281
- return style_party
282
-
283
 
284
 
285
- style_options= ["Measure Status", "Political Party"]
286
-
287
- color_choice = st.radio("Color by:", style_options)
288
-
289
- import leafmap.maplibregl as leafmap
290
- m = leafmap.Map(style="positron", center=(-100, 40), zoom=3)
291
 
292
  if color_choice == "Measure Status":
 
 
 
293
 
294
- #states are 2D and transparent, thus added separately.
295
- m.add_pmtiles(
296
- url,
297
- style=get_style_status("State"),
298
- visible=True,
299
- opacity=0.4,
300
- tooltip=True,
301
- fit_bounds=False
302
- )
303
-
304
- m.add_pmtiles(
305
- url,
306
- style=get_style_status("County"),
307
- visible=True,
308
- opacity=1.0,
309
- tooltip=True,
310
- fit_bounds=False
311
- )
312
-
313
-
314
- m.add_pmtiles(
315
- url,
316
- style=get_style_status("Municipal"),
317
- visible=True,
318
- opacity=1.0,
319
- tooltip=True,
320
- fit_bounds=False
321
- )
322
-
323
- else:
324
- m.add_pmtiles(
325
- url,
326
- style=get_style_party("State"),
327
- visible=True,
328
- opacity=0.6,
329
- tooltip=True,
330
- fit_bounds=False
331
- )
332
-
333
- m.add_pmtiles(
334
- url,
335
- style=get_style_party("County"),
336
- visible=True,
337
- opacity=1.0,
338
- tooltip=True,
339
- fit_bounds=False
340
- )
341
-
342
-
343
- m.add_pmtiles(
344
- url,
345
- style=get_style_party("Municipal"),
346
- visible=True,
347
- opacity=1.0,
348
- tooltip=True,
349
- fit_bounds=False
350
- )
351
-
352
-
353
- m.add_layer_control()
354
 
 
 
355
  m.to_streamlit()
356
 
357
- df_passes = get_passes(party)
358
- percent_chart(df_passes)
359
- funding_chart(party.filter(_.year >= 2000))
360
 
 
 
 
361
 
362
- # st.divider()
363
- # footer = st.container()
364
-
 
1
  import ibis
2
  from ibis import _
 
3
 
4
+ import streamlit as st
5
  import altair as alt
6
+ import os
7
+ import pandas as pd
8
+ import matplotlib.pyplot as plt
9
+ from pandasai.llm.openai import OpenAI
10
+ from pandasai import Agent
11
+ from pandasai.responses.streamlit_response import StreamlitResponse
12
+ import leafmap.maplibregl as leafmap
13
 
14
  st.set_page_config(layout="wide",
15
  page_title="TPL LandVote",
 
22
 
23
  '''
24
 
25
+ COLORS = {
26
+ "dark_orange": "#ab5601",
27
+ "light_orange": "#f3d3b1",
28
+ "grey": "#d3d3d3",
29
+ "light_green": "#c3dbc3",
30
+ "dark_green": "#417d41",
31
+ "dem_blue": "#1b46c2",
32
+ "rep_red": "#E81B23"
33
+ }
34
 
 
 
 
 
 
 
 
 
 
 
35
 
36
+ ## chatbot
37
  llm = OpenAI(api_token=st.secrets["OPENAI_API_KEY"])
38
  df1 = pd.read_csv("data.csv")
39
+ agent = Agent([df1], config={"verbose": True, "response_parser": StreamlitResponse, "llm": llm})
 
 
 
 
 
 
40
 
41
  with st.sidebar:
42
 
 
61
  st.image(im)
62
  os.remove('exports/charts/temp_chart.png')
63
  st.write(resp)
 
64
 
65
+ year = st.slider("Select a year", 1988, 2024, 2022, 1)
66
 
67
+
 
 
68
 
69
+ votes_pmtiles = "https://huggingface.co/datasets/boettiger-lab/landvote/resolve/main/votes.pmtiles"
70
+ votes_parquet = "https://huggingface.co/datasets/boettiger-lab/landvote/resolve/main/votes.parquet"
71
 
72
+ # get parquet data for charts
 
 
73
  con = ibis.duckdb.connect(extensions=["spatial"])
 
74
  party = (con
75
+ .read_parquet(votes_parquet)
76
+ .cast({"geometry": "geometry"})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  )
 
 
 
 
78
 
79
 
80
+ # generate altair chart with df
81
+ def create_chart(df, y_column, title, color):
82
+ # color encoding - color is a list or single value
83
+ color_encoding = (
84
+ alt.Color('party:N', scale=alt.Scale(domain=["DEMOCRAT", "REPUBLICAN"], range=color))
85
+ if isinstance(color, list) else alt.value(color)
86
+ )
87
 
88
+ return alt.Chart(df).mark_line(strokeWidth=3).encode(
89
+ x=alt.X('year:N', title='Year'),
90
+ y=alt.Y(f'{y_column}:Q', title=title),
91
+ color=color_encoding
 
 
 
 
92
  ).properties(
93
+ title=title
94
  )
95
+
96
+ # percentage of measures passing, per party
97
+ def get_passes(party):
98
+ return (party
99
+ .filter(_.year >= 2000)
100
+ .group_by("year", "party")
101
+ .aggregate(total=_.count(), passes=_.Status.isin(["Pass", "Pass*"]).sum())
102
+ .mutate(percent_passed=(_.passes / _.total).round(2),
103
+ color=ibis.case().when(_.party == "DEMOCRAT", COLORS["dem_blue"]).else_(COLORS["rep_red"]).end())
104
+ .to_pandas())
105
 
106
 
107
+ # cumulative funding over time
108
  def funding_chart(party):
109
+ return (party
110
+ .filter(_.year >= 2000)
111
+ .mutate(amount=_.amount.replace('$', '')
112
+ .replace(',', '')
113
+ .cast('float64'))
114
+ .filter(_.Status.isin(["Pass", "Pass*"]))
115
+ .group_by("year")
116
+ .aggregate(total_funding=_.amount.sum())
117
+ .order_by("year")
118
+ .mutate(cumulative_funding=_.total_funding.cumsum()/1e9)
119
+ .to_pandas()
120
+ )
 
 
 
 
121
 
 
 
122
 
123
+ #color fill for measure status
124
  paint_fill = {
125
+ "fill-color": [
126
+ "case",
127
+ ["==", ["get", "Status"], "Pass"],
128
+ [
129
+ "interpolate", ["linear"], [
130
+ "to-number", ["slice", ["get", "yes"], 0, -1] # convert 'yes' string to number
131
+ ],
132
+ 50, COLORS["grey"],
133
+ 55, COLORS["light_green"],
134
+ 100, COLORS["dark_green"] # higher yes % -> darker green
135
+ ],
136
+ ["==", ["get", "Status"], "Fail"],
137
+ [
138
+ "interpolate", ["linear"], [
139
+ "to-number", ["slice", ["get", "yes"], 0, -1]
140
+ ],
141
+ 0, COLORS["dark_orange"],
142
+ 50, COLORS["light_orange"], # lower yes % -> darker orange
143
+ 67, COLORS["grey"] # 67 is max in our data
144
+ ],
145
+ COLORS["grey"]
146
+ ]
147
+ }
 
 
 
148
 
149
+ # for status, height depends on funding
150
  paint_extrusion = {
151
+ "fill-extrusion-color": paint_fill["fill-color"],
152
+ "fill-extrusion-height": ["*", ["to-number", ["get", "log_amount"]], 5000]
153
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
 
155
 
156
+
157
+ # pmtiles style for status
158
  def get_style_status(jurisdiction):
159
  if jurisdiction == "State":
160
  name = "state"
161
  label = "states"
162
  paint_type = paint_fill
163
  layer_type = "fill"
 
164
  elif jurisdiction == "County":
165
  name = "county"
166
  label = "counties"
167
  paint_type = paint_extrusion
168
  layer_type = "fill-extrusion"
169
+ else: # Municipal
 
170
  name = "municipal"
171
  label = "cities"
172
  paint_type = paint_extrusion
173
  layer_type = "fill-extrusion"
174
 
175
+ return {
176
  "layers": [
177
  {
178
  "id": label,
179
  "source": name,
180
  "source-layer": name,
181
  "type": layer_type,
182
+ "filter": ["==", ["get", "year"], year],
 
 
 
 
183
  "paint": paint_type
184
+ }
185
+ ]
186
  }
 
187
 
188
 
189
+ # pmtiles style for party
190
  def get_style_party(jurisdiction):
191
  if jurisdiction == "State":
192
  name = "state"
 
194
  elif jurisdiction == "County":
195
  name = "county"
196
  label = "counties"
197
+ else: # Municipal
 
198
  name = "municipal"
199
  label = "cities"
200
 
201
+ # Return style dictionary for political party
202
+ return {
203
  "layers": [
204
  {
205
+ "id": label,
206
  "source": name,
207
  "source-layer": name,
208
  "type": "fill",
209
  "filter": [
210
+ "==", ["get", "year"], year
 
 
211
  ],
212
  "paint": {
213
+ "fill-color": {
214
+ "property": "party",
215
+ "type": "categorical",
216
+ "stops": [
217
+ ["DEMOCRAT", COLORS["dem_blue"]],
218
+ ["REPUBLICAN", COLORS["rep_red"]]
219
+ ]
 
220
  }
221
  }
222
+ }
223
+ ]
224
  }
 
 
225
 
226
 
227
+ m = leafmap.Map(style="positron", center=(-100, 40), zoom=3)
228
+ color_choice = st.radio("Color by:", ["Measure Status", "Political Party"])
 
 
 
 
229
 
230
  if color_choice == "Measure Status":
231
+ m.add_pmtiles(votes_pmtiles, style=get_style_status("State"), visible=True, opacity=0.4, tooltip=True)
232
+ m.add_pmtiles(votes_pmtiles, style=get_style_status("County"), visible=True, opacity=1.0, tooltip=True)
233
+ m.add_pmtiles(votes_pmtiles, style=get_style_status("Municipal"), visible=True, opacity=1.0, tooltip=True)
234
 
235
+ elif color_choice == "Political Party":
236
+ m.add_pmtiles(votes_pmtiles, style=get_style_party("State"), visible=True, opacity=0.6, tooltip=True)
237
+ m.add_pmtiles(votes_pmtiles, style=get_style_party("County"), visible=True, opacity=1.0, tooltip=True)
238
+ m.add_pmtiles(votes_pmtiles, style=get_style_party("Municipal"), visible=True, opacity=1.0, tooltip=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239
 
240
+ #
241
+ m.add_layer_control()
242
  m.to_streamlit()
243
 
 
 
 
244
 
245
+ # display charts
246
+ df_passes = get_passes(party)
247
+ st.altair_chart(create_chart(df_passes, "percent_passed", "% of Measures Passed", [COLORS["dem_blue"], COLORS["rep_red"]]), use_container_width=True)
248
 
249
+ df_funding = funding_chart(party)
250
+ st.altair_chart(create_chart(df_funding, "cumulative_funding", "Cumulative Funding (Billions of Dollars)", COLORS["dark_green"]))
 
preprocess.ipynb CHANGED
@@ -10,7 +10,7 @@
10
  },
11
  {
12
  "cell_type": "code",
13
- "execution_count": 1,
14
  "id": "6452373c-d10f-472c-9174-cd05a3363587",
15
  "metadata": {},
16
  "outputs": [],
@@ -30,7 +30,7 @@
30
  },
31
  {
32
  "cell_type": "code",
33
- "execution_count": 2,
34
  "id": "dd9ffc64-b4cf-4e5b-9c96-703e91a77837",
35
  "metadata": {},
36
  "outputs": [],
@@ -74,7 +74,7 @@
74
  },
75
  {
76
  "cell_type": "code",
77
- "execution_count": 3,
78
  "id": "8fc40e96-fffd-4b23-9963-c931fdce96f6",
79
  "metadata": {},
80
  "outputs": [],
@@ -105,21 +105,10 @@
105
  },
106
  {
107
  "cell_type": "code",
108
- "execution_count": 4,
109
  "id": "b1cd8f44-57fa-49a8-b438-f9e4aab747c5",
110
  "metadata": {},
111
- "outputs": [
112
- {
113
- "name": "stdout",
114
- "output_type": "stream",
115
- "text": [
116
- "The token has not been saved to the git credentials helper. Pass `add_to_git_credential=True` in this function directly or `--add-to-git-credential` if using via `huggingface-cli` if you want to set the git credential as well.\n",
117
- "Token is valid (permission: write).\n",
118
- "Your token has been saved to /home/rstudio/.cache/huggingface/token\n",
119
- "Login successful\n"
120
- ]
121
- }
122
- ],
123
  "source": [
124
  "import subprocess\n",
125
  "import os\n",
@@ -165,85 +154,10 @@
165
  },
166
  {
167
  "cell_type": "code",
168
- "execution_count": 5,
169
  "id": "7061577e-0632-4395-8ac5-241a1fab53b0",
170
  "metadata": {},
171
- "outputs": [
172
- {
173
- "data": {
174
- "application/vnd.jupyter.widget-view+json": {
175
- "model_id": "ff135769c16340f9a87905b600836afe",
176
- "version_major": 2,
177
- "version_minor": 0
178
- },
179
- "text/plain": [
180
- "FloatProgress(value=0.0, layout=Layout(width='auto'), style=ProgressStyle(bar_color='black'))"
181
- ]
182
- },
183
- "metadata": {},
184
- "output_type": "display_data"
185
- },
186
- {
187
- "data": {
188
- "application/vnd.jupyter.widget-view+json": {
189
- "model_id": "037e0563f82447998bbd438473a2017d",
190
- "version_major": 2,
191
- "version_minor": 0
192
- },
193
- "text/plain": [
194
- "FloatProgress(value=0.0, layout=Layout(width='auto'), style=ProgressStyle(bar_color='black'))"
195
- ]
196
- },
197
- "metadata": {},
198
- "output_type": "display_data"
199
- },
200
- {
201
- "data": {
202
- "application/vnd.jupyter.widget-view+json": {
203
- "model_id": "60716409890f4760a744123d4e6003de",
204
- "version_major": 2,
205
- "version_minor": 0
206
- },
207
- "text/plain": [
208
- "FloatProgress(value=0.0, layout=Layout(width='auto'), style=ProgressStyle(bar_color='black'))"
209
- ]
210
- },
211
- "metadata": {},
212
- "output_type": "display_data"
213
- },
214
- {
215
- "name": "stderr",
216
- "output_type": "stream",
217
- "text": [
218
- "2286 features, 17891307 bytes of geometry and attributes, 58357 bytes of string pool, 0 bytes of vertices, 0 bytes of nodes\n",
219
- "Choosing a maxzoom of -z3 for features typically 83927 feet (25581 meters) apart, and at least 11120 feet (3390 meters) apart\n",
220
- "Choosing a maxzoom of -z10 for resolution of about 278 feet (84 meters) within features\n",
221
- " 99.9% 10/279/424 \n",
222
- " 100.0% 10/55/448 \r"
223
- ]
224
- },
225
- {
226
- "name": "stdout",
227
- "output_type": "stream",
228
- "text": [
229
- "Successfully generated PMTiles file: votes.pmtiles\n"
230
- ]
231
- },
232
- {
233
- "data": {
234
- "application/vnd.jupyter.widget-view+json": {
235
- "model_id": "c8a1a66665814dd8b0ad839929a6b30d",
236
- "version_major": 2,
237
- "version_minor": 0
238
- },
239
- "text/plain": [
240
- "votes.pmtiles: 0%| | 0.00/4.72M [00:00<?, ?B/s]"
241
- ]
242
- },
243
- "metadata": {},
244
- "output_type": "display_data"
245
- }
246
- ],
247
  "source": [
248
  "gdf_state = votes.filter(_.jurisdiction == 'State').execute().set_crs(\"EPSG:4326\")\n",
249
  "gdf_state.to_file(\"votes_state.geojson\")\n",
@@ -260,39 +174,10 @@
260
  },
261
  {
262
  "cell_type": "code",
263
- "execution_count": 6,
264
  "id": "f2979624-bcdf-4a8a-899a-c22fc3cdaf0e",
265
  "metadata": {},
266
- "outputs": [
267
- {
268
- "data": {
269
- "application/vnd.jupyter.widget-view+json": {
270
- "model_id": "6b928b70b56e45a8b1f59c727bd6879a",
271
- "version_major": 2,
272
- "version_minor": 0
273
- },
274
- "text/plain": [
275
- "FloatProgress(value=0.0, layout=Layout(width='auto'), style=ProgressStyle(bar_color='black'))"
276
- ]
277
- },
278
- "metadata": {},
279
- "output_type": "display_data"
280
- },
281
- {
282
- "data": {
283
- "application/vnd.jupyter.widget-view+json": {
284
- "model_id": "0f4fa7e221ff481697375deba7f34b94",
285
- "version_major": 2,
286
- "version_minor": 0
287
- },
288
- "text/plain": [
289
- "votes.parquet: 0%| | 0.00/43.1M [00:00<?, ?B/s]"
290
- ]
291
- },
292
- "metadata": {},
293
- "output_type": "display_data"
294
- }
295
- ],
296
  "source": [
297
  "# save as parquet\n",
298
  "votes.execute().set_crs(\"EPSG:4326\").to_parquet(\"votes.parquet\")\n",
 
10
  },
11
  {
12
  "cell_type": "code",
13
+ "execution_count": null,
14
  "id": "6452373c-d10f-472c-9174-cd05a3363587",
15
  "metadata": {},
16
  "outputs": [],
 
30
  },
31
  {
32
  "cell_type": "code",
33
+ "execution_count": null,
34
  "id": "dd9ffc64-b4cf-4e5b-9c96-703e91a77837",
35
  "metadata": {},
36
  "outputs": [],
 
74
  },
75
  {
76
  "cell_type": "code",
77
+ "execution_count": null,
78
  "id": "8fc40e96-fffd-4b23-9963-c931fdce96f6",
79
  "metadata": {},
80
  "outputs": [],
 
105
  },
106
  {
107
  "cell_type": "code",
108
+ "execution_count": null,
109
  "id": "b1cd8f44-57fa-49a8-b438-f9e4aab747c5",
110
  "metadata": {},
111
+ "outputs": [],
 
 
 
 
 
 
 
 
 
 
 
112
  "source": [
113
  "import subprocess\n",
114
  "import os\n",
 
154
  },
155
  {
156
  "cell_type": "code",
157
+ "execution_count": null,
158
  "id": "7061577e-0632-4395-8ac5-241a1fab53b0",
159
  "metadata": {},
160
+ "outputs": [],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  "source": [
162
  "gdf_state = votes.filter(_.jurisdiction == 'State').execute().set_crs(\"EPSG:4326\")\n",
163
  "gdf_state.to_file(\"votes_state.geojson\")\n",
 
174
  },
175
  {
176
  "cell_type": "code",
177
+ "execution_count": null,
178
  "id": "f2979624-bcdf-4a8a-899a-c22fc3cdaf0e",
179
  "metadata": {},
180
+ "outputs": [],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  "source": [
182
  "# save as parquet\n",
183
  "votes.execute().set_crs(\"EPSG:4326\").to_parquet(\"votes.parquet\")\n",