最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python - How to swap background colour of stripes in arviz.plot_forest - Stack Overflow

programmeradmin0浏览0评论

This might be a simple question but I can't figure it out. In arviz's arviz.plot_forest, how can I swap the order of the shaded backgrounds? For instance, in this example figure from their docs, how can I start with grey and have the odd rows white? Or how do I define and customise this formatting?

Thanks.


Edit after @Onuralp Arslan's answer (6.2.).

The issue I'm facing is that there remains some colour from the original plot, so repainting it to other colours (like red and yellow) works but painting them white for some reason doesn't:

non_centered_data = az.load_arviz_data('non_centered_eight')
centered_data = az.load_arviz_data('centered_eight')
axes = az.plot_forest([non_centered_data, centered_data],
                           model_names = ["non centered eight", "centered eight"],
                           kind='forestplot',
                           var_names=["^the"],
                           filter_vars="regex",
                           combined=True,
                           figsize=(9, 7))
axes[0].set_title('Estimated theta for 8 schools models')


# flip the grey and white
ax=axes[0]
y_ticks = ax.get_yticks()
 
# to calculate where to color / size of plot
y_min, y_max = ax.get_ylim()  
total_height = y_max - y_min  
num_rows = len(y_ticks)  
row_height = total_height / num_rows

# even odd alternate
for i, y in enumerate(y_ticks):
    bottom = y - row_height / 2
    top = y + row_height / 2

    if i % 2 == 0:  
        ax.axhspan(bottom, top, color='white', alpha=1, zorder=0)
    else:  
        ax.axhspan(bottom, top, color='lightgrey', alpha=0.2, zorder=-1)

ax.set_axisbelow(True)

produces:

This might be a simple question but I can't figure it out. In arviz's arviz.plot_forest, how can I swap the order of the shaded backgrounds? For instance, in this example figure from their docs, how can I start with grey and have the odd rows white? Or how do I define and customise this formatting?

Thanks.


Edit after @Onuralp Arslan's answer (6.2.).

The issue I'm facing is that there remains some colour from the original plot, so repainting it to other colours (like red and yellow) works but painting them white for some reason doesn't:

non_centered_data = az.load_arviz_data('non_centered_eight')
centered_data = az.load_arviz_data('centered_eight')
axes = az.plot_forest([non_centered_data, centered_data],
                           model_names = ["non centered eight", "centered eight"],
                           kind='forestplot',
                           var_names=["^the"],
                           filter_vars="regex",
                           combined=True,
                           figsize=(9, 7))
axes[0].set_title('Estimated theta for 8 schools models')


# flip the grey and white
ax=axes[0]
y_ticks = ax.get_yticks()
 
# to calculate where to color / size of plot
y_min, y_max = ax.get_ylim()  
total_height = y_max - y_min  
num_rows = len(y_ticks)  
row_height = total_height / num_rows

# even odd alternate
for i, y in enumerate(y_ticks):
    bottom = y - row_height / 2
    top = y + row_height / 2

    if i % 2 == 0:  
        ax.axhspan(bottom, top, color='white', alpha=1, zorder=0)
    else:  
        ax.axhspan(bottom, top, color='lightgrey', alpha=0.2, zorder=-1)

ax.set_axisbelow(True)

produces:

Share Improve this question edited Feb 6 at 9:05 My Work asked Feb 5 at 16:27 My WorkMy Work 2,5085 gold badges26 silver badges55 bronze badges 2
  • Did you look into the colors= parameter of arviz.plot_forest()? – JohanC Commented Feb 6 at 22:13
  • 1 Re @JohanC, yes, as the docs also states, that is for changing the colour of the lines, it's per model (like hue), not for the background afaik. – My Work Commented Feb 9 at 8:13
Add a comment  | 

2 Answers 2

Reset to default 1

In arviz docs it says

Returns: 1D ndarray of matplotlib Axes or bokeh_figures

Which we can use this information to manipulate style as a matplotlib suggested in here matplotlib.axes.Axes.axhspan

with ax is the return of arviz.plot_forest you can use to stylize

y_limits = ax.get_ylim()
num_rows = len(ax.get_yticklabels())

for i in range(num_rows):
    if i % 2 == 0:  # Even rows (starting from 0)
        ax.axhspan(i - 0.5, i + 0.5, color="lightgrey", alpha=0.5)  # Grey shading
    else:  # Odd rows
        ax.axhspan(i - 0.5, i + 0.5, color="white", alpha=0.5)  # White shading

edit:

You can make any color i have use red and yellow to indicate change just edit color names as you like.

You can expand on this idea with

import arviz as az
import numpy as np
import matplotlib.pyplot as plt

param1 = np.random.randn(100)
param2 = np.random.randn(100)
param3 = np.random.randn(100)
param4 = np.random.randn(100)
param5 = np.random.randn(100)

inference_data = az.from_dict(posterior={
    "param1": param1,
    "param2": param2,
    "param3": param3,
    "param4": param4,
    "param5": param5
})

fig, ax = plt.subplots()
az.plot_forest(inference_data, ax=ax)

y_ticks = ax.get_yticks()
 
# to calculate where to color / size of plot
y_min, y_max = ax.get_ylim()  
total_height = y_max - y_min  
num_rows = len(y_ticks)  
row_height = total_height / num_rows

# even odd alternate
for i, y in enumerate(y_ticks):
   
    bottom = y - row_height / 2
    top = y + row_height / 2

    if i % 2 == 0:  
        ax.axhspan(bottom, top, color='yellow', alpha=0.2, zorder=0)
    else:  
        ax.axhspan(bottom, top, color='red', alpha=0.2, zorder=0)

ax.set_axisbelow(True)
plt.show()

Which results

Ok, I found a workaround. The issue was that arviz is producing patches for coloured stripes that stay there and no patches for white stripes. So one first has to remove these patches before proceeding with the solution outlined by Onuralp Arslan, thank you for that idea. It is not possible to just repaint the patches as they do not exist for the white background. Note that the repainting can be done in only two lines if one of the colours is white, such as:

if i % 2 != 0:
    axes[0].axhspan(bottom, top, color='lightgrey', alpha=0.2, zorder=-1)

The full code is:

non_centered_data = az.load_arviz_data('non_centered_eight')
centered_data = az.load_arviz_data('centered_eight')
axes = az.plot_forest([non_centered_data, centered_data],
                           model_names = ["non centered eight", "centered eight"],
                           kind='forestplot',
                           var_names=["^the"],
                           filter_vars="regex",
                           combined=True,
                           figsize=(9, 7))
axes[0].set_title('Estimated theta for 8 schools models')

# remove the grey background
for ax in axes:
    for i, patch in enumerate(ax.patches):
        patch.set_facecolor("none")
        patch.set_edgecolor("none")

# now repaint the stripes as proposed by Onuralp Arslan
y_ticks = axes[0].get_yticks()
 
# to calculate where to color / size of plot
y_min, y_max = ax.get_ylim()  
total_height = y_max - y_min  
num_rows = len(y_ticks)  
row_height = total_height / num_rows

# even odd alternate
for i, y in enumerate(y_ticks):
    bottom = y - row_height / 2
    top = y + row_height / 2

    if i % 2 == 0:
        axes[0].axhspan(bottom, top, color='white', alpha=1, zorder=0)
    else:  
        axes[0].axhspan(bottom, top, color='lightgrey', alpha=0.2, zorder=-1)

which produces the required:

发布评论

评论列表(0)

  1. 暂无评论