Search code examples
pythonmatplotlibseabornarray-broadcastingerrorbar

How to create asymmetric errorbars without triggering broadcast error?


I'm trying to plot some asymmetric error bars using seaborn. I can't understand why I'm getting a ValueError: operands could not be broadcast together with shapes (3,1) (2,3)

Here is my code:

import numpy as np
import matplotlib.pyplot as plt

truth = np.array([0.15725964, 0.15611989, 0.15820897])
hpd = np.array([[0.00310974, 0.01833195],
                        [0.00546891, 0.017973  ],
                        [0.00687474, 0.01628064]])
median = np.array([[0.15517015],[0.12985473],[0.12510344]])

with sns.plotting_context('notebook', font_scale=1.2):

    fig, axmatrix = plt.subplots(ncols=2, figsize=(16,8))
    for ax in axmatrix.flatten():
        ax.set_aspect('equal')

    def plot_hpd_err(truth, hpd, median):        
        err = np.absolute(np.transpose(hpd - [email protected]((1,2))))
            
        return ax.errorbar(truth[:,np.newaxis], median, yerr=err)
 
plot_hpd_err(truth, hpd, median)
  • If I comment out the yerr=err, the code runs fine.
  • The shapes of truth[:,np.newaxis], median, and err are (3,1); (3,1); and (2,3) respectively.
  • I formatted err to be (2,N) shape because that's what the axes.errorbar documentation tells me to do
  • when I transpose truth[:, np.newaxis] and hpd to match err's shape, it throws an error.

Ultimately, I want three data points with their respective asymmetric errorbars, but I'm currently not able to get an ErrorbarContainer object without any errors (yes, the plots are currently blank...)


Solution

  • The size of truth and hpd must be (N,); it cannot be (N, 1). Therefore, the code should read

    import seaborn as sns
    import numpy as np
    import matplotlib.pyplot as plt
    
    truth = np.array([0.15725964, 0.15611989, 0.15820897])
    hpd = np.array([[0.00310974, 0.01833195],
                            [0.00546891, 0.017973  ],
                            [0.00687474, 0.01628064]])
    median = np.array([0.15517015, 0.12985473, 0.12510344])
    
    with sns.plotting_context('notebook', font_scale=1.2):
    
        fig, axmatrix = plt.subplots(ncols=2, figsize=(16,8))
        for ax in axmatrix.flatten():
            ax.set_aspect('equal')
    
        def plot_hpd_err(truth, hpd, median):        
            err = np.absolute(np.transpose(hpd - (median[:, np.newaxis])@np.ones((1,2))))
                
            return ax.errorbar(truth, median, yerr=err)
     
    plot_hpd_err(truth, hpd, median)
    

    Thanks to this answer for helping me figure this out.