Spaces:
Sleeping
Sleeping
import ibis | |
from ibis import _ | |
import streamlit as st | |
st.set_page_config(layout="wide", | |
page_title="TPL LandVote", | |
page_icon=":globe:") | |
''' | |
# LandVote Prototype | |
An experimental platform for visualizing data on ballot measures for conservation, based on data from <https://landvote.org/> curated by the Trust for Public Land. | |
''' | |
## Chatbot | |
import os | |
import pandas as pd | |
import matplotlib.pyplot as plt | |
from pandasai.llm.openai import OpenAI | |
from pandasai import Agent | |
from pandasai.responses.streamlit_response import StreamlitResponse | |
llm = OpenAI(api_token=st.secrets["OPENAI_API_KEY"]) | |
df1 = pd.read_csv("data.csv") | |
agent = Agent( | |
[df1], | |
config={"verbose": True, "response_parser": StreamlitResponse, "llm": llm}, | |
) | |
with st.sidebar: | |
''' | |
## Data Assistant (experimental) | |
Ask questions about the landvote data, like: | |
- What are the top states for approved conservation funds? | |
- Plot the total funds spent in conservation each year. | |
- What city has approved the most funds in a single measure? What was the description of that vote? | |
- Which state has had largest number measures fail? What is that as a fraction of it's total measures? | |
''' | |
prompt = st.chat_input("Ask about the data") | |
if prompt: | |
with st.spinner(): | |
resp = agent.chat(prompt) | |
if os.path.isfile('exports/charts/temp_chart.png'): | |
im = plt.imread('exports/charts/temp_chart.png') | |
st.image(im) | |
os.remove('exports/charts/temp_chart.png') | |
st.write(resp) | |
# year = st.slider("Select a year", min_value=1988, max_value=2024, value=2022, step=2) | |
year = st.slider("Select a year", min_value=1988, max_value=2024, value=2022, step=1) | |
import leafmap.maplibregl as leafmap | |
m = leafmap.Map(style="positron", center=(-100, 40), zoom=3) | |
url = "https://huggingface.co/datasets/boettiger-lab/landvote/resolve/main/landvote.pmtiles" | |
dark_orange = 'rgba(171, 86, 1, 1)' # dark orange - min value | |
light_orange = 'rgba(243, 211, 177, 1)' # light orange | |
grey = 'rgba(211, 211, 211, 1)' # grey | |
light_green = 'rgba(195, 219, 195, 1)' # light green | |
dark_green = 'rgba(65, 125, 65, 1)' # dark green - max value | |
style_municipals = { | |
"layers": [ | |
{ | |
"id": "municipals", | |
"source": "municipal", | |
"source-layer": "municipal", | |
"type": "fill-extrusion", | |
"filter": [ | |
"==", | |
["get", "year"], | |
year, | |
], | |
"paint": { | |
"fill-extrusion-color": [ | |
"case", | |
# if passed, color green | |
["==", ["get", "Status"], "Pass"], | |
[ | |
"interpolate", ["linear"], [ | |
"to-number", ["slice", ["get", "yes"], 0, -1] # convert 'yes' string to number | |
], | |
50, grey, | |
55, light_green, # higher yes % -> darker green | |
100, dark_green # 100 is the max of data | |
], | |
# if failed, color orange | |
["==", ["get", "Status"], "Fail"], | |
[ | |
"interpolate", ["linear"], [ | |
"to-number", ["slice", ["get", "yes"], 0, -1] # convert 'yes' string to number | |
], | |
0, dark_orange, # higher yes % -> lighter orange | |
50, light_orange, | |
67, grey # 67 is the max of data. | |
], | |
grey # if no match | |
], | |
"fill-extrusion-height": ["*", ["get", "log_amount"], 5000], | |
} | |
}, | |
], | |
} | |
style_counties = { | |
"layers": [ | |
{ | |
"id": "counties", | |
"source": "county", | |
"source-layer": "county", | |
"type": "fill-extrusion", | |
"filter": [ | |
"==", | |
["get", "year"], | |
year, | |
], | |
"paint": { | |
"fill-extrusion-color": [ | |
"case", | |
# if passed, color green | |
["==", ["get", "Status"], "Pass"], | |
[ | |
"interpolate", ["linear"], [ | |
"to-number", ["slice", ["get", "yes"], 0, -1] # convert 'yes' string to number | |
], | |
50, grey, | |
55, light_green, # higher yes % -> darker green | |
100, dark_green # 100 is the max of data | |
], | |
# if failed, color orange | |
["==", ["get", "Status"], "Fail"], | |
[ | |
"interpolate", ["linear"], [ | |
"to-number", ["slice", ["get", "yes"], 0, -1] # convert 'yes' string to number | |
], | |
0, dark_orange, # higher yes % -> lighter orange | |
50, light_orange, | |
67, grey # 67 is the max of data. | |
], | |
grey # if no match | |
], | |
"fill-extrusion-height": ["*", ["get", "log_amount"], 5000], | |
} | |
}, | |
], | |
} | |
style_states = { | |
"layers": [ | |
{ | |
"id": "states", | |
"source": "state", | |
"source-layer": "state", | |
"type": "fill", | |
"filter": [ | |
"==", | |
["get", "year"], | |
year, | |
], | |
"paint": { | |
"fill-color": [ | |
"case", | |
# if passed, color green | |
["==", ["get", "Status"], "Pass"], | |
[ | |
"interpolate", ["linear"], [ | |
"to-number", ["slice", ["get", "yes"], 0, -1] # convert 'yes' string to number | |
], | |
50, grey, | |
55, light_green, # higher yes % -> darker green | |
100, dark_green # 100 is the max of data | |
], | |
# if failed, color orange | |
["==", ["get", "Status"], "Fail"], | |
[ | |
"interpolate", ["linear"], [ | |
"to-number", ["slice", ["get", "yes"], 0, -1] # convert 'yes' string to number | |
], | |
0, dark_orange, # higher yes % -> lighter orange | |
50, light_orange, | |
67, grey # 67 is the max of data. | |
], | |
grey # if no match | |
] | |
} | |
}, | |
], | |
} | |
#states are 2D and transparent, thus added separately. | |
m.add_pmtiles( | |
url, | |
style=style_states, | |
visible=True, | |
opacity=0.6, | |
tooltip=True, | |
fit_bounds=False | |
) | |
#states are 2D and transparent, thus added separately. | |
m.add_pmtiles( | |
url, | |
style=style_counties, | |
visible=True, | |
opacity=0.6, | |
tooltip=True, | |
fit_bounds=False | |
) | |
m.add_pmtiles( | |
url, | |
style=style_municipals, | |
visible=True, | |
opacity=1.0, | |
tooltip=True, | |
fit_bounds=False | |
) | |
m.add_layer_control() | |
m.to_streamlit() | |