【问题标题】:How to plot min/max bars with a bar plot如何用条形图绘制最小/最大条形图
【发布时间】:2021-02-24 00:13:34
【问题描述】:

我想调整我的绘图代码以显示如下图所示的最小/最大条:

我的代码是:

from datetime import datetime, timedelta
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style("white")
sns.set_style('darkgrid',{"axes.facecolor": ".92"}) # (1)
sns.set_context('notebook')

Delay = ['S1', 'S2', 'S3', 'S4']

Time = [87, 66, 90, 55]

df = pd.DataFrame({'Delay':Delay,'Time':Time})
print("Accuracy")

display(df) # in jupyter

fig, ax = plt.subplots(figsize = (8,6))

x = Delay
y = Time

plt.xlabel("Delay", size=14)
plt.ylim(-0.3, 100)
width = 0.1

for i, j in zip(x,y): 
    ax.bar(i,j, edgecolor = "black",
        error_kw=dict(lw=1, capsize=1, capthick=1))  
    ax.set(ylabel = 'Accuracy')

from matplotlib import ticker
ax.yaxis.set_major_locator(ticker.MultipleLocator(10)) 
plt.savefig("Try.png", dpi=300, bbox_inches='tight')

代码生成这个图:

我要添加的最小值/最大值是:

87 (60-90)
66 (40-70)
90 (80-93)
55 (23-60)

提前感谢您的帮助。

【问题讨论】:

    标签: python pandas matplotlib seaborn


    【解决方案1】:
    import pandas as pd
    import matplotlib.pyplot as plt
    import seaborn as sns
    
    # set edgecolor param (this is a global setting, so only set it once)
    plt.rcParams["patch.force_edgecolor"] = True
    
    # setup the dataframe
    Delay = ['S1', 'S2', 'S3', 'S4']
    
    Time = [87, 66, 90, 55]
    
    df = pd.DataFrame({'Delay':Delay,'Time':Time})
    
    # create a dict for the errors
    error = {87: {'max': 90,'min': 60}, 66: {'max': 70,'min': 40}, 90: {'max': 93,'min': 80}, 55: {'max': 60,'min': 23}}
    

    seaborn.barplot

    • seaborn.barplot 将自动添加错误栏,如链接中的示例所示。但是,这是特定于使用许多数据点的。在这种情况下,一个值被指定为错误,错误不是从数据中确定的。
      • 这样添加误差线时,可以指定capsize参数,在误差线的顶部和底部添加水平线。
    # plot the figure
    fig, ax = plt.subplots(figsize=(8, 6))
    sns.barplot(x='Delay', y='Time', data=df, ax=ax)
    
    # add the lines for the errors 
    for p in ax.patches:
        x = p.get_x()  # get the bottom left x corner of the bar
        w = p.get_width()  # get width of bar
        h = p.get_height()  # get height of bar
        min_y = error[h]['min']  # use h to get min from dict z
        max_y = error[h]['max']  # use h to get max from dict z
        plt.vlines(x+w/2, min_y, max_y, color='k')  # draw a vertical line
    

    • 正如gepcel 中的answer 中所述,yerr 参数可用于向 API 显式提供错误。
      • 但是,您的错误格式与参数不正确。 yerr 期望值与栏的顶部相关
        • S1 为 87,min 或 60,max 为 90。因此,ymin 为 27,(87-60),ymax 为 3,(90-87)。
    • seaborn.barplotcapsize 参数似乎不适用于yerr,因此您必须设置matplotlib 'errorbar.capsize' rcParmas。见Matplotlib Errorbar Caps Missing
    # set capsize param (this is a global setting, so only set it once)
    plt.rcParams['errorbar.capsize'] = 10
    
    # create dataframe as shown by gepcel
    Delay = ['S1', 'S2', 'S3', 'S4']
    
    Time = [87, 66, 90, 55]
    _min = [60, 40, 80, 23]
    _max = [90, 70, 93, 60]
    df = pd.DataFrame({'Delay':Delay,'Time':Time, 'Min': _min, 'Max': _max})
    
    # create ymin and ymax
    df['ymin'] = df.Time - df.Min
    df['ymax'] = df.Max - df.Time
    
    # extract ymin and ymax into a (2, N) array as required by the yerr parameter
    yerr = df[['ymin', 'ymax']].T.to_numpy()
    
    # plot with error bars
    fig, ax = plt.subplots(figsize=(8, 6))
    sns.barplot(x='Delay', y='Time', data=df, yerr=yerr, ax=ax)
    

    pandas.DataFrame.plot.bar

    fig, ax = plt.subplots(figsize=(8, 6))
    
    df.plot.bar(x='Delay', ax=ax)
    
    for p in ax.patches:
        x = p.get_x()  # get the bottom left x corner of the bar
        w = p.get_width()  # get width of bar
        h = p.get_height()  # get height of bar
        min_y = error[h]['min']  # use h to get min from dict z
        max_y = error[h]['max']  # use h to get max from dict z
        plt.vlines(x+w/2, min_y, max_y, color='k')  # draw a vertical line
    

    ax.bar

    fig, ax = plt.subplots(figsize=(8, 6))
    
    ax.bar(x='Delay', height='Time', data=df)
    
    for p in ax.patches:
        x = p.get_x()  # get the bottom left x corner of the bar
        w = p.get_width()  # get width of bar
        h = p.get_height()  # get height of bar
        min_y = error[h]['min']  # use h to get min from dict z
        max_y = error[h]['max']  # use h to get max from dict z
        plt.vlines(x+w/2, min_y, max_y, color='k')  # draw a vertical line
    

    【讨论】:

      【解决方案2】:

      您可以直接使用plt.baryerr arg。以@Trenton McKinney 的代码为例:

      import pandas as pd
      import matplotlib.pyplot as plt
      
      # setup the dataframe
      Delay = ['S1', 'S2', 'S3', 'S4']
      
      Time = [87, 66, 90, 55]
      _min = [60, 40, 80, 23]
      _max = [90, 70, 93, 60]
      df = pd.DataFrame({'Delay':Delay,'Time':Time, 'Min': _min, 'Max': _max})
      df = (df.assign(yerr_min = df.Time-df.Min)
              .assign(yerr_max=df.Max-df.Time))
      
      plt.figure(figsize=(8, 6))
      plt.bar(x='Delay', height='Time', yerr=df[['yerr_min', 'yerr_max']].T.values, capsize=10, data=df)
      
      plt.show()
      

      【讨论】:

        【解决方案3】:

        这是使用yerrnumpy 的解决方案。它的样板代码比@gepcel 的少。

        import matplotlib.pyplot as plt
        import numpy as np
        
        # setup the dataframe
        Delay = ['S1', 'S2', 'S3', 'S4']
        
        Time = [87, 66, 90, 55]
        _min = [60, 40, 80, 23]
        _max = [90, 70, 93, 60]
        
        plt.figure(figsize=(8, 6))
        
        yerr = [np.subtract(Time, _min), np.subtract(_max, Time)]
        plt.bar(Delay, Time, yerr=yerr, capsize=10)
        
        plt.show()
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-01-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-12
          • 1970-01-01
          • 2020-06-23
          相关资源
          最近更新 更多