St.line_chart, Altair.Chart and Pandas issue

Summary

Hello,

I have the following Panda DataFrame:

2023-03-09 14:48:12.144 Columns: Index([One', 'Two'], dtype='object')
2023-03-09 14:48:12.145 Index: DatetimeIndex(['2023-03-09 19:48:12.124000072',
               '2023-03-09 19:48:42.124000072',
               '2023-03-09 19:49:12.124000072',
               '2023-03-09 19:49:42.124000072',
               '2023-03-09 19:50:12.124000072',
               '2023-03-09 19:50:42.124000072',
               '2023-03-09 19:51:12.124000072',
               '2023-03-09 19:51:42.124000072',
               '2023-03-09 19:52:12.124000072',
               '2023-03-09 19:52:42.124000072'],
              dtype='datetime64[ns]', freq=None)
2023-03-09 14:48:12.150 Index:                                One  Two
2023-03-09 19:48:12.124000072     1.087717e+09           4.165702e+09
2023-03-09 19:48:42.124000072     1.087717e+09           4.165702e+09
2023-03-09 19:49:12.124000072     1.087717e+09           4.165702e+09
2023-03-09 19:49:42.124000072     1.087717e+09           4.165702e+09
2023-03-09 19:50:12.124000072     1.087717e+09           4.165702e+09
2023-03-09 19:50:42.124000072     1.087717e+09           4.165702e+09
2023-03-09 19:51:12.124000072     1.087717e+09           4.165702e+09
2023-03-09 19:51:42.124000072     1.087717e+09           4.165702e+09
2023-03-09 19:52:12.124000072     1.087717e+09           4.165702e+09
2023-03-09 19:52:42.124000072     1.087717e+09           4.165702e+09

But I cannot get the plot renderered:

chart = alt.Chart(data).mark_line().encode()

Expected behavior:

Have a time series data rendered

** Workaround:**

Using st.line_chart works out of the box:

st.line_chart(data=data)

Actual behavior:

No chart is created is Altair is used

Debug info

  • Streamlit version: 1.19.0
  • Python version: 3.10
  • Using Pip
  • OS version: Linux Fedora 36
  • Browser version: Brave

Requirements file

pip==23.0.1
setuptools==67.4.0
wheel==0.38.4
streamlit==1.19.0
pandas~=1.5.3
requests==2.28.2

Altair plots require much more work than that. This should work:

chart = (
    altair.Chart(data.stack().rename("value").reset_index())
    .mark_line()
    .encode(x="Index:", y="value", color="level_1")
)

Hello @Goyo ,

I tried your suggestion as follows:

                            chart = (
                                altair.Chart(data.stack().rename("value").reset_index()).mark_line().encode(
                                    x="Index:",
                                    y="value",
                                    color="level_1"
                                )
                            )
                            st.altair_chart(chart, use_container_width=True)

But then I get the following exception:

ValueError: Index: encoding field is specified without a type; the type cannot be inferred because it does not match any column in the data.
Traceback:
...
File "/home/josevnz/virtualenv/Streamlit/lib/python3.11/site-packages/altair/vegalite/v4/schema/channels.py", line 40, in to_dict
    raise ValueError("{} encoding field is specified without a type; "

I recreated the data from you somewhat messy textual description so it might not be exactly the same.

You either need to learn altair or keep using st.line_plot().

@Goyo,

I’ll figure out what is throwing Altair off, the DataFrame description is straightforward (one DatetimeIndex index and two Float columns).

In any case thanks for looking into this.

From the examples you are missing the types for the axis. Try:

chart = (
                  altair.Chart(data.stack().rename("value").reset_index()).mark_line().encode(
                      x="Index:T",
                      y="value:Q",
                      color="level_1"
                  )
              )
              st.altair_chart(chart, use_container_width=True)

Hello @CarlosSerrano ,

The plot looks much better, but for some reason the ‘X’ axis is not being populated (no errors on the console).

I was checking again the documentation Streamlit Altair and Original Altair documentation, I think this is very close!

Looking at the OP again it looks like your index doesn’t have a name, so it would become level_0 after resetting the index.

chart = (
    altair.Chart(data.stack().rename("value").reset_index())
    .mark_line()
    .encode(x="level_0", y="value", color="level_1")
    .interactive()
)

@Goyo,

Got it, I’m still pretty much green with Pandas and the library itself. I ended doing the following:

                            chart = (
                                altair.Chart(data.stack().rename("value").reset_index()).mark_line().encode(
                                    x="level_0:T",
                                    y="value:Q",
                                    color="level_1"
                                )
                            )
                            st.altair_chart(chart, use_container_width=True)

Thanks to both of you!

–Jose

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.