File size: 6,192 Bytes
1e84f36
 
 
7ce1b29
1e84f36
 
7ce1b29
1e84f36
 
7ce1b29
1e84f36
 
 
 
7ce1b29
1e84f36
 
7ce1b29
1e84f36
 
7ce1b29
1e84f36
 
 
7020c63
1e84f36
 
 
7020c63
1e84f36
 
 
 
7020c63
1e84f36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7020c63
1e84f36
 
 
 
 
 
 
7020c63
1e84f36
 
7020c63
1e84f36
7020c63
1e84f36
7020c63
1e84f36
 
 
 
7020c63
1e84f36
 
7020c63
1e84f36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77e694f
f3a8e80
c12e2e7
 
 
 
47a82ac
 
1e84f36
c12e2e7
 
 
 
 
 
1e84f36
c12e2e7
 
 
 
 
 
 
 
 
 
 
 
1e84f36
 
 
 
d2fe28a
1e84f36
 
 
 
7ce1b29
1e84f36
 
 
5e2422c
1e84f36
 
5e2422c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# import panel as pn
# import pandas as pd
# import altair as alt

# # we want to use bootstrap/template, tell Panel to load up what we need
# pn.extension(design='bootstrap')

# # we want to use vega, tell Panel to load up what we need
# pn.extension('vega')

# # create a basic template using bootstrap
# template = pn.template.BootstrapTemplate(
#     title='SI649 Altair Assignment',
# )

# # the main column will hold our key content
# maincol = pn.Column()

# # add some markdown to the main column
# maincol.append("# Polling Data Interactive Visualization")

# # load up a dataframe and show it in the main column
# 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'})

# # Selection widgets
# subgroup_select = pn.widgets.Select(name='Select', options=['Adults', 'Voters', 'All polls'])
# date_slider = pn.widgets.DateRangeSlider(name='Date Range Slider', start=df2['timestamp'].min(), end=df2['timestamp'].max())
# moving_avg_slider = pn.widgets.IntSlider(name='Moving Average Window', start=1, end=100, step=1)

# # Bind the widgets to the create_plot function
# @pn.depends(subgroup_select.param.value, date_slider.param.value, moving_avg_slider.param.value)
# def create_plot(subgroup, date_range, moving_av_window):
#     data = df2[(df2['subgroup'] == subgroup) & (df2['choice'] == "approve") & (df2['timestamp'].dt.date.between(date_range[0], date_range[1]))]
#     min_rate = df2['rate'].min()
#     max_rate = df2['rate'].max()

#     data = data.sort_values('timestamp')
#     data['moving_avg'] = data['rate'].rolling(window=moving_av_window, min_periods=1).mean()

#     # Line chart for moving average
#     line = alt.Chart(data).mark_line(interpolate='natural').encode(
#         x=alt.X('timestamp:T', axis=alt.Axis(title='', format='%b %d, %Y')),
#         y=alt.Y('moving_avg:Q', axis=alt.Axis(title='approve,mov_avg'), scale=alt.Scale(domain=[min_rate, max_rate])),
#         color=alt.value('red')
#     )

#     # Scatter plot for individual data points
#     points = alt.Chart(data).mark_point().encode(
#         x=alt.X('timestamp:T'),
#         y=alt.Y('rate:Q', axis=alt.Axis(title='approve,mov_avg'), scale=alt.Scale(domain=[min_rate, max_rate])),
#         color=alt.value('gray'),
#         tooltip=['timestamp:T', 'rate:Q']
#     )

#     # Combine line chart and scatter plot
#     plot = alt.layer(points, line).resolve_scale(y='shared')

#     return plot

# # app = pn.Column("# Polling Data Interactive Visualization", pn.panel(create_plot, reactive=True), subgroup_select, date_slider, moving_avg_slider)

# maincol.append(pn.panel(create_plot, reactive=True))
# maincol.append(subgroup_select)
# maincol.append(date_slider)
# maincol.append(moving_avg_slider)

# # add the main column to the template
# template.main.append(maincol)

# # Indicate that the template object is the "application" and serve it
# template.servable(title="SI649 Altair Assignment")


import panel as pn
import pandas as pd
import altair as alt

# Ensure Panel and Altair extensions are loaded
pn.extension('vega', design='bootstrap')

# 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")

# Data preprocessing
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'})

# Widgets
subgroup_select = pn.widgets.Select(name='Select Subgroup', options=['Adults', 'Voters', 'All polls'])
date_slider = pn.widgets.DateRangeSlider(name='Date Range Slider', start=df2['timestamp'].min(), end=df2['timestamp'].max())
moving_avg_slider = pn.widgets.IntSlider(name='Moving Average Window', start=1, end=100, step=1)

# Visualization function
@pn.depends(subgroup_select.param.value, date_slider.param.value, moving_avg_slider.param.value)
def create_plot(subgroup, date_range, moving_av_window):
    start_date, end_date = date_range[0], date_range[1] # Convert to date
    data = df2[(df2['subgroup'] == subgroup) & (df2['choice'] == "approve")  & (pd.to_datetime(df2['timestamp']) >= pd.to_datetime(start_date)) & (pd.to_datetime(df2['timestamp']) <= pd.to_datetime(end_date))]
    
    min_rate = df2['rate'].min()
    max_rate = df2['rate'].max()
    
    data = data.sort_values('timestamp')
    data['moving_avg'] = data['rate'].rolling(window=moving_av_window, min_periods=1).mean()

    # Line chart for moving average
    line = alt.Chart(data).mark_line(interpolate='natural').encode(
        x=alt.X('timestamp:T', axis=alt.Axis(title='', format='%b %d, %Y')),
        y=alt.Y('moving_avg:Q', axis=alt.Axis(title='approve,mov_avg'), scale=alt.Scale(domain=[min_rate, max_rate])),
        color=alt.value('red')
    )

    # Scatter plot for individual data points
    points = alt.Chart(data).mark_point().encode(
        x=alt.X('timestamp:T'),
        y=alt.Y('rate:Q', axis=alt.Axis(title='approve,mov_avg'), scale=alt.Scale(domain=[min_rate, max_rate])),
        color=alt.value('gray'),
        tooltip=['timestamp:T', 'rate:Q']
    )

    # Combine line chart and scatter plot
    plot = alt.layer(points, line).resolve_scale(y='shared')

    return plot

# Main layout
main_layout = pn.Column(
    "# Polling Data Interactive Visualization",
    pn.panel(create_plot, reactive=True),
    subgroup_select,
    date_slider,
    moving_avg_slider,
)

# Create a basic template
template = pn.template.BootstrapTemplate(title='SI649 Altair Assignment')
template.main.append(main_layout)

# Serve the application
template.servable()