import numpy as np import pandas as pd import altair as alt import panel as pn # Data import df2=pd.read_csv("https://raw.githubusercontent.com/dallascard/SI649_public/main/altair_hw3/approval_topline.csv") 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(design='bootstrap') pn.extension('vega') template = pn.template.BootstrapTemplate( title='Nan-Hsin Lin', ) # Define a function to create and return a plot def create_plot(subgroup, date_range, moving_av_window): # Apply any required transformations to the data in pandas df3 = df2[df2['choice'] == 'approve'].copy() df3 = df3[df3['subgroup'] == subgroup] df3['smoothed_rate'] = df3['rate'].rolling(moving_av_window).mean().shift(-int(moving_av_window/2)) start_date, end_date = date_range df3 = df3[(df3['timestamp'] >= np.datetime64(start_date)) & (df3['timestamp'] <= np.datetime64(end_date))] # Line chart rate_line = alt.Chart(df3).mark_line(strokeWidth=2, color='red').encode( x=alt.X('timestamp:T', axis=alt.Axis(title=None)), y=alt.Y('average(smoothed_rate):Q', axis=alt.Axis(title='move_avg'), scale=alt.Scale(domain=[30, 60])) ) # Scatter plot with individual polls rate_scatter = alt.Chart(df3).mark_point(color='grey', size=2, opacity=0.7).encode( x=alt.X('timestamp:T', axis=alt.Axis(title=None)), y=alt.Y('rate:Q', axis=alt.Axis(title='approve'), scale=alt.Scale(domain=[30, 60])), ) # Put them together plot = alt.layer(rate_line, rate_scatter).configure_view(strokeWidth=0) # Return the combined chart return plot # Create the selection widget select = pn.widgets.Select(name='Select', options=df2['subgroup'].unique().tolist()) # Create the slider for the date range dateSlider = pn.widgets.DateRangeSlider(name='Date Range Slider', start=df2['timestamp'].min(), end=df2['timestamp'].max(), value=(df2['timestamp'].min(), df2['timestamp'].max())) # Create the slider for the moving average window avgSlider = pn.widgets.IntSlider(name='Moving average window', start=1, end=100, value=1) # Bind the widgets to the create_plot function plot_widgets = pn.Row(pn.bind(create_plot, select, dateSlider, avgSlider)) # Combine everything in a Panel Column to create an app maincol = pn.Column() maincol.append("# SI649 Lab07") maincol.append("Hello! This is **Nan**. I love information visualization! Email me: [nanhsin@umich.edu](mailto:nanhsin@umich.edu)") maincol.append(plot_widgets) maincol.append(select) maincol.append(dateSlider) maincol.append(avgSlider) template.main.append(maincol) # set the app to be servable template.servable(title="Nan-Hsin Lin")