si649_panel / app3.py
chriskok3's picture
Update app3.py
6939d6e verified
# supress warnings about future deprecations
import warnings
warnings.simplefilter(action='ignore', category=FutureWarning)
import pandas as pd
import altair as alt
import numpy as np
import pprint
import datetime as dt
from vega_datasets import data
import matplotlib.pyplot as plt
# Import panel and vega datasets
import panel as pn
import vega_datasets
df2=pd.read_csv("https://raw.githubusercontent.com/dallascard/SI649_public/main/altair_hw3/approval_topline.csv")
# fix the time stamps and reorganize the data to combine approve and disapprove into one column
df2['timestamp']=pd.to_datetime(df2['timestamp'])
df2=pd.melt(df2, id_vars=['president', 'subgroup', 'timestamp'], value_vars=['approve','disapprove']).rename(columns={'variable':'choice', 'value':'rate'})
# Enable Panel extensions
pn.extension('vega')
# we want to use bootstrap/template, tell Panel to load up what we need
# pn.extension(design='bootstrap')
# Define a function to create and return a plot
def create_plot(subgroup='All polls', date_range=[df2['timestamp'].min(), df2['timestamp'].max()], moving_av_window=1):
# Downselection!
approval_df2 = df2.copy()
approval_df2 = approval_df2[approval_df2['subgroup'] == subgroup]
approval_df2 = approval_df2[approval_df2['choice'] == 'approve']
# remove columns
approval_df2 = approval_df2.drop(columns=['choice', 'subgroup', 'president'])
# convert date_range to datetime
date_range = [pd.to_datetime(date_range[0]), pd.to_datetime(date_range[1])]
# narrow down dates
approval_df2 = approval_df2[
(approval_df2['timestamp'] >= date_range[0]) &
(approval_df2['timestamp'] <= date_range[1])
]
# Apply any required transformations to the data in pandas
smooth_data = approval_df2.sort_values('timestamp').rolling(window=moving_av_window, on='timestamp', center=True).mean().shift(-moving_av_window+1)
chart_data = approval_df2.sort_values('timestamp').copy()
# Line chart
line = alt.Chart(smooth_data).mark_line(color='red', size=2).encode(
x=alt.X('timestamp:T', scale=alt.Scale(domain=date_range)),
y=alt.Y('rate:Q', scale=alt.Scale(domain=[30, 60]), title='approve, mov_avg'),
)
# Scatter plot with individual polls
scatter = alt.Chart(chart_data).mark_point(size=2, opacity=0.7, color='grey').encode(
x=alt.X('timestamp:T', scale=alt.Scale(domain=date_range)),
y=alt.Y('rate:Q', scale=alt.Scale(domain=[30, 60]))
)
# Put them together
plot = alt.layer(scatter, line).resolve_scale(y='shared')
# Return the combined chart
return plot
# Create the selection widget
subgroup_select = pn.widgets.Select(name='Select subgroup', options=['Adults', 'All polls', 'Voters'])
# Create the slider for the date range
date_range_slider = pn.widgets.DateRangeSlider(name='Date range slider', end=df2['timestamp'].max(), start=df2['timestamp'].min(), value=(df2['timestamp'].min(), df2['timestamp'].max()))
# Create the slider for the moving average window
moving_av_slider = pn.widgets.IntSlider(name='Moving average window', start=1, end=100, value=1)
# Bind the widgets to the create_plot function
@pn.depends(subgroup_select.param.value, date_range_slider.param.value, moving_av_slider.param.value)
def reactive_plot(subgroup, date_range, moving_av_window):
return create_plot(subgroup, date_range, moving_av_window)
# Combine everything in a Panel Column to create an app
app = pn.Column(reactive_plot, subgroup_select, date_range_slider, moving_av_slider)
# Set the app to be servable
app.servable()