Last active
February 26, 2021 15:57
-
-
Save sjtalkar/bdd310b15392fb40ef053bfb5b114c7e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import altair as alt | |
from vega_datasets import data | |
# uses intermediate json files to speed things up | |
alt.data_transformers.enable('json') | |
domain_stock_list = ["AAPL", "DIS", "FB", "MSFT", "NFLX", "TSLA"] | |
def getBaseChart(): | |
""" | |
Creates a chart by encoding the Data along the X positional axis and rolling mean along the Y positional axis | |
The mark (bar/line..) can be decided upon by the calling function. | |
""" | |
base = ( | |
alt.Chart(stock_df) | |
.encode( | |
x=alt.X( | |
"Date:T", | |
axis=alt.Axis(title=None, format=("%b %Y"), labelAngle=0, tickCount=6), | |
), | |
y=alt.Y( | |
"rolling_mean:Q", axis=alt.Axis(title="Close (rolling mean in USD)") | |
), | |
) | |
.properties(width=500, height=400) | |
) | |
return base | |
def getSelection(): | |
""" | |
This function creates a selection element and uses it to "conditionally" set a color for a categorical variable (stock). | |
It return both the single selection as well as the Category for Color choice set based on selection | |
""" | |
radio_select = alt.selection_multi( | |
fields=["stock"], name="Stock", | |
) | |
stock_color_condition = alt.condition( | |
radio_select, alt.Color("stock:N", legend=None), alt.value("lightgrey") | |
) | |
return radio_select, stock_color_condition | |
def createChart(): | |
""" | |
This function uses the "base" encoding chart to create a line chart. | |
The highlight_stocks variable uses the mark_line function to create a line chart out of the encoding. | |
The color of the line is set using the conditional color set for the categorical variable using the selection. | |
The chart is bound to the selection using add_selection. | |
It also creates a selector element of a vertical array of circles so that the user can select between stocks | |
""" | |
radio_select, stock_color_condition = getSelection() | |
make_selector = ( | |
alt.Chart(stock_df) | |
.mark_circle(size=200) | |
.encode( | |
y=alt.Y("stock:N", axis=alt.Axis(title="Pick Stock", titleFontSize=15)), | |
color=stock_color_condition, | |
) | |
.add_selection(radio_select) | |
) | |
base = getBaseChart() | |
highlight_stocks = ( | |
base.mark_line(strokeWidth=2) | |
.add_selection(radio_select) | |
.encode(color=stock_color_condition) | |
).properties(title="Rolling Average of Stock Close") | |
return base, make_selector, highlight_stocks, radio_select | |
def createTooltip(base, radio_select): | |
""" | |
This function uses the "base" encoding chart and the selection captured. | |
Four elements related to selection are created here | |
""" | |
# Create a selection that chooses the nearest point & selects based on x-value | |
nearest = alt.selection( | |
type="single", nearest=True, on="mouseover", fields=["Date"], empty="none" | |
) | |
# Transparent selectors across the chart. This is what tells us | |
# the x-value of the cursor | |
selectors = ( | |
alt.Chart(stock_df) | |
.mark_point() | |
.encode( | |
x="Date:T", | |
opacity=alt.value(0), | |
) | |
.add_selection(nearest) | |
) | |
# Draw points on the line, and highlight based on selection | |
points = base.mark_point(size=5, dy=-10).encode( | |
opacity=alt.condition(nearest, alt.value(1), alt.value(0)) | |
).transform_filter(radio_select) | |
# Draw text labels near the points, and highlight based on selection | |
tooltip_text = base.mark_text( | |
align="left", | |
dx=-60, | |
dy=-15, | |
fontSize=15, | |
fontWeight="bold", | |
lineBreak = "\n", | |
).encode( | |
text=alt.condition( | |
nearest, | |
alt.Text("rolling_mean:Q", format=".2f"), | |
alt.value(" "), | |
), | |
).transform_filter(radio_select) | |
# Draw a rule at the location of the selection | |
rules = ( | |
alt.Chart(stock_df) | |
.mark_rule(color="black", strokeWidth=2) | |
.encode( | |
x="Date:T", | |
) | |
.transform_filter(nearest) | |
) | |
return selectors, rules, points, tooltip_text | |
def getImageLayer(): | |
""" | |
This function adds an image title to the chart. The Image is stored in relative path data | |
""" | |
img_layer = ( | |
alt.Chart({"values": [{"url": "data/FooterImageForArticle.PNG"}]}) | |
.mark_image(align="left") | |
.encode( | |
x=alt.value(-100), | |
x2=alt.value(650), | |
y=alt.value(0), | |
y2=alt.value(50), # pixels from top | |
url="url:N", | |
) | |
.properties( | |
# set the dimensions of the visualization | |
width=600, | |
height=50, | |
) | |
) | |
return img_layer | |
base, make_selector, highlight_stocks, radio_select = createChart() | |
selectors, rules, points, tooltip_text = createTooltip(base, radio_select) | |
img_layer = getImageLayer() | |
### Bring all the layers together with layering and concatenation | |
img_layer & (make_selector | alt.layer(highlight_stocks, selectors, points,rules, tooltip_text )) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment