Search code examples
pythonplotlydata-visualizationplotly-python

How to remove x-axis tick labels in a stacked-and-grouped bar chart using Plotly


I have a dataset:

Dataset

I want to visualise this dataset in a stacked-and-grouped bar chart using Plotly. Unfortunately, Plotly does not have this type of charts yet, but there is this workaround that I tried.

My code:

sv_clusters = ["cluster_1", "cluster_2", "cluster_3", "cluster_4", "cluster_5", "cluster_6", "cluster_7"]
sv_data = sv_data[["Population", "Sample_name"] + sv_clusters]

for r in sv_clusters:
    fig.add_trace(
        go.Bar(
            x=[sv_data.Population, sv_data.Sample_name],
            y=sv_data[r],
            name=r,
            marker=dict(
                line_width=0)),
    )

fig.update_layout(
    template="simple_white",
    xaxis=dict(title_text=None),
    yaxis=dict(title_text="fraction"),
    width=2000,
    bargap=0,
    title='Alles',
    barmode="stack",

Now my plot looks like this:

plot1

I want to remove the x-label ticks, since it clutters the chart (sample names not the population names). So I tried showticklabels=False, which resulted in this:

plot2

Which removes all x-axis labels.

How do I remove the sample name tick labels?


Solution

  • import requests
    import pandas as pd
    import numpy as np
    import plotly.graph_objects as go
    
    # generate some data... similar to what was presented
    sv_data = pd.DataFrame(
        {
            "Population": pd.json_normalize(
                requests.get("https://restcountries.eu/rest/v2/all").json()
            )["subregion"].unique()
        }
    ).loc[0:6,].assign(
        Sample_name=lambda d: d["Population"]
        .str[:2]
        .str.upper()
        .apply(lambda s: [f"{s}{i}" for i in range(1500, 1550)])
    ).explode(
        "Sample_name"
    ).assign(**{f"cluster_{i}":lambda d: np.random.uniform(0,1, len(d)) for i in range(1,8)})
    
    sv_clusters = ["cluster_1", "cluster_2", "cluster_3", "cluster_4", "cluster_5", "cluster_6", "cluster_7"]
    sv_data = sv_data[["Population", "Sample_name"] + sv_clusters]
    fig=go.Figure()
    
    # instead of categoricals use concatenated value for x,  define text to hover works
    for r in sv_clusters:
        fig.add_trace(
            go.Bar(
                x=sv_data.loc[:,["Population","Sample_name"]].apply(lambda r: " ".join(r), axis=1),
                y=sv_data[r],
                text=sv_data.loc[:,["Population","Sample_name"]].apply(lambda r: " ".join(r), axis=1),
                name=r,
                marker=dict(
                    line_width=0)),
        )
    
    # given simple x,  set tick vals as wanted
    fig.update_layout(
        template="simple_white",
        yaxis=dict(title_text="fraction"),
        width=2000,
        bargap=0,
        title='Alles',
        barmode="stack",
        xaxis={"tickmode":"array", "tickvals":sv_data.loc[:,["Population","Sample_name"]].apply(lambda r: " ".join(r), axis=1),
              "ticktext":np.where(sv_data["Population"]==sv_data["Population"].shift(), "", sv_data["Population"])}
    )
    
    
    

    enter image description here