Auto expanding chart

Hi, need help with this:

I created an Altair chart and sized it to fit into an expander in a multi-widget page. I use the command “cht_expander.write(cht)” and everything works fine.

However, I wish that the chart auto-expands into the container. Something like when we do “st.altair_chart(cht, use_container_width=True)”

If I use “cht_expander.write(st.altair_chart(cht, use_container_width=True))”, it displays my chart outside the container

What should I change the code to?

Thanks in advance

Hi @Shawn_Pereira,

The desired behavior can be achieved by replacing cht_expander.write with cht_expander.altair_chart. Here’s a before/after comparison:

Before:

df = pd.DataFrame(np.random.randn(200, 3), columns=['a', 'b', 'c'])

cht = alt.Chart(df).mark_circle().encode(
    x='a', y='b', size='c', color='c', tooltip=['a', 'b', 'c'])

cht_expander = st.expander('expander', expanded=False)
cht_expander.write(cht, use_container_width=True)

After:

df = pd.DataFrame(np.random.randn(200, 3), columns=['a', 'b', 'c'])

cht = alt.Chart(df).mark_circle().encode(
    x='a', y='b', size='c', color='c', tooltip=['a', 'b', 'c'])

cht_expander = st.expander('expander', expanded=False)
cht_expander.altair_chart(cht, use_container_width=True)

Does this help?

Happy Streamlit’ing! :balloon:
Snehan

1 Like

Thank you @snehankekre for the prompt response. Your solution works perfectly for a single chart. However, it does not work for a multilayered chart using the following code:

cht = alt.layer(cht1, cht2, cht3)
cht_expander.altair_chart(cht, use_container_width=True)

do let me know if I can do something for this too.

Your help is very much appreciated. :slight_smile:

Hi @Shawn_Pereira,

I used this example of a multilayered chart from the Altair documentation and it does work:
https://altair-viz.github.io/gallery/layered_chart_with_dual_axis.html

import streamlit as st
import altair as alt
from vega_datasets import data

source = data.seattle_weather()

base = alt.Chart(source).encode(
    alt.X('month(date):T', axis=alt.Axis(title=None))
)

cht1 = base.mark_area(opacity=0.3, color='#57A44C').encode(
    alt.Y('average(temp_max)',
          axis=alt.Axis(title='Avg. Temperature (°C)', titleColor='#57A44C')),
    alt.Y2('average(temp_min)')
)

cht2 = base.mark_line(stroke='#5276A7', interpolate='monotone').encode(
    alt.Y('average(precipitation)',
          axis=alt.Axis(title='Precipitation (inches)', titleColor='#5276A7'))
)

use_container_width = False
if st.checkbox('Use container width', True):
    use_container_width=True

cht_expander = st.expander('expander', expanded=False)

cht_expander.altair_chart(
    alt.layer(cht1, cht2).resolve_scale(
        y = 'independent'
    ), use_container_width=use_container_width
)

altair-multilayer

It would help if you could share a reproducible code snippet of the issue you face :slightly_smiling_face:

Best, :balloon:
Snehan

@snehankekre, sorry for the late response. It didn’t work for me. A snippet of my code is:

mdf = st.session_state.dflst[st.session_state.vsidx].copy()
ux = st.session_state.dflst[st.session_state.vsidx].get(“VISIT PVAL”).max(axis = 0) + 1 # incr y cood axis scale by 1 so plotting does not touch top of graph
cht1 = alt.Chart(mdf[(mdf[“SCNID”] == tmpsid) & (mdf[“VISIT PARAMETER”] == tmpparam)])
cht1 = cht1.mark_line(color = “blue”, point = True)
cht1 = cht1.encode(alt.X(“VISIT”, title = “Visit”), alt.Y(“LOW”, title = “Visit Value”, scale = alt.Scale(domain=(0, ux))))
# cht1 = cht1.encode(alt.Color(‘VISIT:N’))
cht1 = cht1.properties(width = 500, height = 300, title = “Reading per Visit”)

                cht2 = alt.Chart(mdf[(mdf["SCNID"] == tmpsid) & (mdf["VISIT PARAMETER"] == tmpparam)])
                cht2 = cht2.mark_line(color = "orange", point = True)
                cht2 = cht2.encode(alt.X("VISIT", title = "Visit"), alt.Y("VISIT PVAL", title = "Visit Value", scale = alt.Scale(domain=(0, ux))))
                # cht2 = cht2.encode(alt.Color('VISIT:N'))
                cht2 = cht2.properties(width = 500, height = 300, title = "Reading per Visit")
                
                cht3 = alt.Chart(mdf[(mdf["SCNID"] == tmpsid) & (mdf["VISIT PARAMETER"] == tmpparam)])
                cht3 = cht3.mark_line(color = "red", point = True)
                cht3 = cht3.encode(alt.X("VISIT", title = "Visit"), alt.Y("HIGH", title = "Visit Value", scale = alt.Scale(domain=(0, ux))))
                # cht3 = cht3.encode(alt.Color('VISIT:N'))
                cht3 = cht3.properties(width = 500, height = 300, title = "Reading per Visit")
                
                cht = alt.layer(cht1, cht2, cht3)

                cht = cht.configure_title(fontSize=20, font="Courier", anchor="start", color="red")
                
                st.altair_chart(cht, use_container_width=True)
                # st.write(cht)
                st.markdown('<span style="color:black">Legend Colour: </span><span style="color:red">Upper Limit, </span><span style="color:orange">Visit Value, </span><span style="color:blue">Lower Limit</span>', unsafe_allow_html=True,)

Maybe, I am missing something…

Shawn