Python >> Tutoriel Python >  >> Python Tag >> Plotly

Plotly :Comment masquer les titres des axes dans une figure plotly express à facettes ?

Cette réponse comporte cinq parties :

  1. Masquer les titres des intrigues secondaires (mais pas sûr à 100 % que vous vouliez le faire...)
  2. Masquer les valeurs de graduation de l'axe Y à l'aide de fig.layout[axis].tickfont = dict(color = 'rgba(0,0,0,0)')
  3. Définir des étiquettes d'axe unique à l'aide de go.layout.Annotation(xref="paper", yref="paper")
  4. la figure de l'intrigue
  5. Extrait de code complet à la fin

Une conclusion très importante ici est que vous pouvez modifier n'importe quel élément produit avec un px fonction utilisant plotly.graph_object références, comme go.layout.XAxis .

1. Masquer les titres des sous-parcelles

Si vous êtes satisfait de la façon dont vous avez configuré votre fig , vous pouvez simplement inclure

for anno in fig['layout']['annotations']:
    anno['text']=''
    
fig.show()

2. Masquer le texte yaxis

Vous pouvez définir le tickfont yaxis sur transparent en utilisant ce qui suit dans une boucle

fig.layout[axis].tickfont = dict(color = 'rgba(0,0,0,0)')

Cette ligne exacte est incluse dans l'extrait ci-dessous qui supprime également le titre de l'axe y pour chaque sous-parcelle.

3. Étiquettes à axe unique

La suppression des étiquettes d'axe et l'inclusion d'une seule étiquette nécessitent un peu plus de travail, mais voici une configuration très flexible qui fait exactement ce dont vous avez besoin et plus si vous souhaitez modifier vos nouveaux libellés de quelque manière que ce soit :

# hide subplot y-axis titles and x-axis titles
for axis in fig.layout:
    if type(fig.layout[axis]) == go.layout.YAxis:
        fig.layout[axis].title.text = ''
    if type(fig.layout[axis]) == go.layout.XAxis:
        fig.layout[axis].title.text = ''
        
# keep all other annotations and add single y-axis and x-axis title:
fig.update_layout(
    # keep the original annotations and add a list of new annotations:
    annotations = list(fig.layout.annotations) + 
    [go.layout.Annotation(
            x=-0.07,
            y=0.5,
            font=dict(
                size=16, color = 'blue'
            ),
            showarrow=False,
            text="single y-axis title",
            textangle=-90,
            xref="paper",
            yref="paper"
        )
    ] +
    [go.layout.Annotation(
            x=0.5,
            y=-0.08,
            font=dict(
                size=16, color = 'blue'
            ),
            showarrow=False,
            text="Dates",
            textangle=-0,
            xref="paper",
            yref="paper"
        )
    ]
)

fig.show()

4. Terrain

5. Code complet :

import pandas as pd
import numpy as np
import plotly.express as px
import string
import plotly.graph_objects as go

# create a dataframe
cols = list(string.ascii_letters)
cols[0]='zzz'
n = 50

df = pd.DataFrame({'Date': pd.date_range('2021-01-01', periods=n)})

# create data with vastly different ranges
for col in cols:
    start = np.random.choice([1, 10, 100, 1000, 100000])
    s = np.random.normal(loc=0, scale=0.01*start, size=n)
    df[col] = start + s.cumsum()

# melt data columns from wide to long
dfm = df.melt("Date")

fig = px.line(
    data_frame=dfm,
    x = 'Date',
    y = 'value',
    facet_col = 'variable',
    facet_col_wrap=6,
    #facet_col_spacing=0.05,
    #facet_row_spacing=0.035,
    height = 1000,
    width = 1000,
    title = 'Value vs. Date'
)

fig.update_yaxes(matches=None, showticklabels=True, visible=True)
fig.update_annotations(font=dict(size=16))
fig.for_each_annotation(lambda a: a.update(text=a.text.split("=")[-1]))

# subplot titles
for anno in fig['layout']['annotations']:
    anno['text']=''

# hide subplot y-axis titles and x-axis titles
for axis in fig.layout:
    if type(fig.layout[axis]) == go.layout.YAxis:
        fig.layout[axis].title.text = ''
    if type(fig.layout[axis]) == go.layout.XAxis:
        fig.layout[axis].title.text = ''
        
# keep all other annotations and add single y-axis and x-axis title:
fig.update_layout(
    # keep the original annotations and add a list of new annotations:
    annotations = list(fig.layout.annotations) + 
    [go.layout.Annotation(
            x=-0.07,
            y=0.5,
            font=dict(
                size=16, color = 'blue'
            ),
            showarrow=False,
            text="single y-axis title",
            textangle=-90,
            xref="paper",
            yref="paper"
        )
    ] +
    [go.layout.Annotation(
            x=0.5,
            y=-0.08,
            font=dict(
                size=16, color = 'blue'
            ),
            showarrow=False,
            text="Dates",
            textangle=-0,
            xref="paper",
            yref="paper"
        )
    ]
)


fig.show()

En remarque à ce sujet, j'ai trouvé un moyen encore plus direct d'éliminer les étiquettes d'axe de l'appel plotly express en utilisant l'argument labels et en lui fournissant un dict d'étiquettes avec des valeurs de '' pour celles que je voulais éliminer.

Cela ne se traduit pas par une seule étiquette au niveau global de la figure, mais si le titre de la figure est suffisamment descriptif de "Y contre X", alors peut-être que le manque d'étiquettes d'axe peut être "excusé" ? (ou ajouté comme @vestland l'a démontré)

Notez que vous pouvez "presque" éliminer les titres de facette répétés ennuyeux qui ont "=valeur" dans chaque sous-lot. c'est-à-dire si vous ajoutez une entrée supplémentaire au dict des étiquettes :

'variable' :''

puis au lieu d'obtenir "variable=variable level", vous obtenez simplement la facette variable level, précédée du "=" comme dans le tableau ci-dessous.

Code complet

import pandas as pd
import numpy as np
import plotly.express as px
import string

# create a dataframe
cols = list(string.ascii_letters)
n = 50

df = pd.DataFrame({'Date': pd.date_range('2021-01-01', periods=n)})

# create data with vastly different ranges
for col in cols:
    start = np.random.choice([1, 10, 100, 1000, 100000])
    s = np.random.normal(loc=0, scale=0.01*start, size=n)
    df[col] = start + s.cumsum()

# melt data columns from wide to long
dfm = df.melt("Date")

# make the plot
fig = px.line(
    data_frame=dfm,
    x = 'Date',
    y = 'value',
    facet_col = 'variable',
    facet_col_wrap=6,
    facet_col_spacing=0.05,
    facet_row_spacing=0.035,
    height = 1000,
    width = 1000,
    title = 'Value vs. Date',
    labels = {
        'Date': '',
        'value': '',
        'variable': ''
    }
)

# ensure that each chart has its own y rage and tick labels
fig.update_yaxes(matches=None, showticklabels=True, visible=True)

fig.show()