vega / altair

Declarative statistical visualization library for Python
https://altair-viz.github.io/
BSD 3-Clause "New" or "Revised" License
9.39k stars 795 forks source link

docs: Add `ThemeConfig` section to User Guide #3645

Open dangotbanned opened 1 month ago

dangotbanned commented 1 month ago

Description

Work-in-progress

What

Show how this benefits:

Typing users

Non-typing users

Where

Either

Related

Have you considered any alternative solutions?

We can leave chart-themes in the same state as left by #3618

I think @joelostblom's comment shows why this feature warrants further explanation.

The only alternative I see would be linking to typing-spec-TypedDict. However, I did this in #3536-description and that alone did not suffciently convey the benefits to reviewers

mattijn commented 8 hours ago

Explain it in benefits. As a person who is not into types it is really hard to understand the differences between mypy, pylance and pyright. I cannot remember what is best in which occasions. But if I get benefits when it is installed that are useful during development then that is appreciated. For example, I can imagine that it is a nice benefit if one can get on-the-fly validation of your Altair specification while you are writing it. Altair provides already very nice feedback when one runs the code and if there is something wrong with it. But with the Pylance extension installed in MS VS code, you also will get yellow wavy underlines provides direct feedback giving you suggestions how you can make your Altair specification while you are writing it. You can make your specification better and correct without actually running it.

[!IMPORTANT] The following is only tested in VSCode with the Pylance extension installed

Start with a basic chart:

import altair as alt
import pandas as pd

data = pd.DataFrame({'x': [5, 3, 6, 7, 2],
                     'y': ['A', 'B', 'C', 'D', 'E']})
chart = alt.Chart(data).mark_bar().encode(
    x='x',
    y='y',
)
chart

Start writing the following to define your own valid Altair theme.

from altair.theme import ThemeConfig

def my_theme():
    return ThemeConfig(
        config={

        }
    )

It will look like this.

No wavy underlines visible, yet.

If I add a single (!) " quote on the empty line below config={ then VScode will automatically add a second " and position your mouse cursor in between and pop up a supportive screen with valid Altair elements that can but used to define your theme.

You can use all elements that are in between double quotes "<valid-altair-element>". The list shows more elements than the valid ones. The last valid element is in this case "view":

If you press escape the supportive screen will disappear and now when hovering with your mouse over the wavy underlines it provide you with information what is currently detected as incorrect:

Write the following character-by-character, "bar": {"color": "black"} and observe what happens if you receive on-the-fly feedback on what is valid:

So no we have a custom_theme function that returns a standard python dictionary.

Nothing special about the output, just a dict, but while writing the dictionary we received on-the-fly suggestions.

[!NOTE] It's called a TypedDict, learn more about this here:

To register this function as a theme in Altair we have to add some magic (a decorator).

from altair.theme import ThemeConfig
from altair.theme import register

@register("my_little_theme", enable=True)
def custom_theme():
    return ThemeConfig(
        config={
            "bar":{"color":"black"}
        }
    )

We import the decorator so we can register our custom_theme function as theme. We name it my_little_theme, and in fact, we enable it directly (=True).

And now, when we call our bar chart chart again, we will notice that it has applied our theme:

If you like to go back to the default theme, you can enable it with:

alt.theme.enable('default')

Now, when calling chart again, it appears as normal:

If you like to use a predefined theme. Call the following function:

alt.theme.names()

Pick one from the following list:

['carbong10',
 'carbong100',
 'carbong90',
 'carbonwhite',
 'dark',
 'default',
 'excel',
 'fivethirtyeight',
 'ggplot2',
 'googlecharts',
 'latimes',
 'my_little_theme',
 'none',
 'opaque',
 'powerbi',
 'quartz',
 'urbaninstitute',
 'vox']

As such:

alt.theme.enable('dark')

[!TIP] Remember you always can you back to the default using

alt.theme.enable('default')

Something like this would be very helpful already. If I use a LLM to "make it better", then the wording is better already. If you do a few iterations, I'm sure you can write something clear and concise and helpful!

dangotbanned commented 8 hours ago

https://github.com/vega/altair/issues/3645#issuecomment-2493829661

Really appreciate this @mattijn thank you!