import vega_datasets import panel as pn import pandas as pd import altair as alt from vega_datasets import data pn.extension(design='bootstrap') # we want to use vega, tell Panel to load up what we need pn.extension('vega') template = pn.template.BootstrapTemplate( title='SI649 Lab7 Viz4', ) # Import panel and vega datasets # load data df1 = pd.read_csv( "https://raw.githubusercontent.com/dallascard/SI649_public/main/altair_hw3/approval_polllist.csv") 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'}) df2.head() # Enable Panel extensions pn.extension() # 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 # print(pd.to_datetime(df2['timestamp']), type(date_range[0])) # df2_filtered = df2[(df2['subgroup'] == subgroup) & (df2['timestamp'] >= date_range[0]) & (df2['timestamp'] <= date_range[1])] df2_filtered = df2[(df2['subgroup'] == subgroup) & (df2['timestamp'] >= pd.Timestamp( date_range[0])) & (df2['timestamp'] <= pd.Timestamp(date_range[1]))] # Calculate the moving average # df2_filtered['moving_rate'] = df2_filtered['rate'].rolling(window=moving_av_window).mean() df2_filtered['moving_rate'] = df2_filtered['rate'].rolling( window=moving_av_window).mean().shift(-moving_av_window//2) # df2_filtered.loc[:, 'moving_rate'] = df2_filtered['rate'].rolling(window=moving_av_window).mean() # # Line chart for moving average with df2_filtered line = alt.Chart(df2_filtered).mark_line().encode( x='timestamp:T', y='moving_rate:Q', color=alt.value('red') ).transform_filter( # keep only approved polls alt.FieldOneOfPredicate(field='choice', oneOf=['approve']) ) # Scatter plot with individual polls scatter = alt.Chart(df2_filtered).mark_circle().encode( x='timestamp:T', y='rate:Q', color=alt.value('gray'), opacity=alt.value(0.7), tooltip=['timestamp:T', 'rate:Q'], size=alt.value(10) ).transform_filter( # keep only approved polls alt.FieldOneOfPredicate(field='choice', oneOf=['approve']) ) # Put them together plot = scatter + line # change y axis range of the plot to 30 to 60 # plot = plot + line plot = plot.properties(title="Approval Ratings for Joe Biden") plot = plot.encode( y=alt.Y('rate:Q', scale=alt.Scale(domain=[30, 60])) ) # Return the combined chart return plot # Create the selection widget using subgroup column selection_subgroup = pn.widgets.Select( name='Subgroup', options=df2.subgroup.unique().tolist()) # Create the slider for the date range df2['timestamp'] = pd.to_datetime(df2['timestamp']) date_range_slider = pn.widgets.DateRangeSlider(name='Date Range', start=df2.timestamp.min( ), end=df2.timestamp.max(), value=(df2.timestamp.min(), df2.timestamp.max())) # Create the slider for the moving average window moving_av_window_slider = pn.widgets.IntSlider( name='Moving Average Window', start=1, end=30, step=1, value=1) # Bind the widgets to the create_plot function create_plot_wgt = pn.bind(create_plot, subgroup=selection_subgroup, date_range=date_range_slider, moving_av_window=moving_av_window_slider) # Combine everything in a Panel Column to create an app main_col = pn.Column( create_plot_wgt, selection_subgroup, date_range_slider, moving_av_window_slider, ) # set the app to be servable main_col.servable()