Search code examples
pythondataframematplotliblabel

Highlight a specific xlabel value in matplotlib


Here is my DataFrame ...

data = {'PEOI': [190, 105, 100, 150, 100, 170], 'PCHOI': [11, 6, 3, 16, 21, 8], 'STKS': [200, 250, 300, 350, 400, 450], 'CCHOI': [3, 8, 13, 18, 3, 23], 'CEOI': [154, 190, 578, 611, 736, 420]}
df = pd.DataFrame(data)
print(df)

I'm plotting this DataFrame as ...

plt.style.use("dark_background")
fig, axes = plt.subplots(2, 1, figsize=(17,15))
for (y1, y2), ax in zip([("CEOI", "PEOI"), ("CCHOI", "PCHOI")], axes):
      ax.bar(df["STKS"], df[y1], width=13, label=y1,color = 'blue')
      ax.bar(df["STKS"], df[y2], width=7, label=y2,color = 'yellow')
      ax.set_xlabel("STRIKES", fontsize=24, fontweight="bold", labelpad=10, color ='cyan')
      ax.set_ylabel("OPEN INTEREST", fontweight="bold", fontsize=24, labelpad=10)
      ax.set_xticks(df["STKS"].values)
      ax.tick_params(labelsize=20)
      ax.tick_params(axis="x", rotation=90)
      ax.legend(fontsize=18)
      if y1 == "CEOI":
        ax.set_title("OPEN INTEREST",fontsize=26,fontweight="bold", loc="left", color ='yellow')
      elif y1 == "CCHOI":
        ax.set_title("CHANGE IN OPEN INTEREST",fontsize=24,fontweight="bold", loc="left", color ='yellow')
      ax.grid(axis="y", linestyle=(0, (15, 8)), alpha=0.4) and ax.set_axisbelow(True)
      #ax.grid()
      for p in ax.patches:
            ax.annotate(format(p.get_height(), '.0f'),
                        (p.get_x() + p.get_width() / 2., p.get_height()),
                        ha='center', va='center',
                        xytext=(1.5, 4),
                        textcoords='offset points',
                        fontsize=16, fontweight="bold")
fig.tight_layout()
plt.show(block=True)

Plz how to highlight any desired value of my xlabel(let's say "350" in STRIKES) with desired colour and fontsize. Thanks.


Solution

  • You can define a mapper of the labels and their formatting outside the very first loop, then get_xticklabels to set_backgroundcolor and set_fontsize :

    
    d = {
        "350": {
            "bg_color": "red", "font_size": 25
        },
        # add more mappings if needed
    }
    
    # rest of the code
        for p in ax.patches:
            # rest of the code
            
        for t in ax.get_xticklabels():
            if (xtl:=t.get_text()) in d :
                t.set_backgroundcolor(d[xtl]["bg_color"])
                t.set_fontsize(d[xtl]["font_size"])
    
    # rest of the code
    

    Output :

    enter image description here


    FULL CODE (asked by OP) :

    import pandas as pd
    import matplotlib.pyplot as plt
    
    data = {'PEOI': [190, 105, 100, 150, 100, 170], 'PCHOI': [11, 6, 3, 16, 21, 8], 'STKS': [200, 250, 300, 350, 400, 450], 'CCHOI': [3, 8, 13, 18, 3, 23], 'CEOI': [154, 190, 578, 611, 736, 420]}
    
    df = pd.DataFrame(data)
    
    d = {
        "350": {
            "bg_color": "red", "font_size": 25
        },
        # add more mappings if needed
    }
    
    plt.style.use("dark_background")
    
    fig, axes = plt.subplots(2, 1, figsize=(17,15))
    
    for (y1, y2), ax in zip([("CEOI", "PEOI"), ("CCHOI", "PCHOI")], axes):
        ax.bar(df["STKS"], df[y1], width=13, label=y1,color = 'blue')
        ax.bar(df["STKS"], df[y2], width=7, label=y2,color = 'yellow')
        ax.set_xlabel("STRIKES", fontsize=24, fontweight="bold", labelpad=10, color ='cyan')
        ax.set_ylabel("OPEN INTEREST", fontweight="bold", fontsize=24, labelpad=10)
        ax.set_xticks(df["STKS"].values)
        ax.tick_params(labelsize=20)
        ax.tick_params(axis="x", rotation=90)
        ax.legend(fontsize=18)
    
        if y1 == "CEOI":
            ax.set_title("OPEN INTEREST",fontsize=26,fontweight="bold", loc="left", color ='yellow')
        elif y1 == "CCHOI":
            ax.set_title("CHANGE IN OPEN INTEREST",fontsize=24,fontweight="bold", loc="left", color ='yellow')
            ax.grid(axis="y", linestyle=(0, (15, 8)), alpha=0.4) and ax.set_axisbelow(True)
        
        for p in ax.patches:
            ax.annotate(format(p.get_height(), '.0f'),
                        (p.get_x() + p.get_width() / 2., p.get_height()),
                        ha='center', va='center',
                        xytext=(1.5, 4),
                        textcoords='offset points',
                        fontsize=16, fontweight="bold")
    
        for t in ax.get_xticklabels():
            if (xtl:=t.get_text()) in d :
                t.set_backgroundcolor(d[xtl]["bg_color"])
                t.set_fontsize(d[xtl]["font_size"])
                
    fig.tight_layout()
    plt.show(block=True);