show error bar in multi line plot using matplotlib

让人想犯罪 __ 提交于 2021-02-19 06:13:44

问题


I've created a multi line plot using marplot lib, and now I want to show the min-max value for each parameter on X-axis. My code is below:

import numpy as np
import pandas as pd
from pandas import DataFrame
import matplotlib.pyplot as plt
from matplotlib import pyplot as plt
import seaborn as sns

df = pd.DataFrame({'Time': ['D=0','D=2','D=5','D=X'],
    'Latency': [74.92, 75.32, 79.64, 100],
    'Delay': [18.2,80,82,84]
   })

  plt.plot( 'Time', 'Latency', data=df, marker='s', color='black', markersize=4,     linewidth=1, linestyle='--')
  plt.plot( 'Time', 'Delay', data=df, marker='o', color='black',  markersize=4, linewidth=1,linestyle='-')

   plt.legend()
   plt.xlabel("Time")
   plt.ylabel("Average Score (%)")
   plt.ylim(0, 100)
   plt.xlim('D=0','D=X')
   plt.savefig('Fig2.png', dpi=300, bbox_inches='tight')
   plt.show()

The interval min-max that I want to add is:

Latency: 
D=0 => {73.3, 76}
D=2 => {73.3, 80}
D=5 => {75, 83.3}
D=X => {100}
Delay:
D=0 => {0, 50}
D=2 => {50, 100}
D=5 => {68, 90}
D=X => {75, 90}

Thanks so much in advance


回答1:


First put the error values in lists:

latency_lower_err = [73.3, 73.3, 75, 100]
latency_upper_err = [76, 80, 83.3, 100]

Then subtract the data points from these values, because matplotlib needs the distance (in absolute units) from the error limit to the corresponding data point:

latency_lower_err = (latency_lower_err - df['Latency']).abs() 
latency_upper_err = (latency_upper_err - df['Latency']).abs()

Put the resulting values in a list, where the first element is the lower errors, and the second element is the upper errors:

yerr = [latency_lower_err, latency_upper_err]

Then change the call from plt.plot to plt.errorbar, adding the yerr argument:

plt.errorbar('Time', 'Latency', data=df, yerr=yerr, capsize=5, ... )

The remaining arguments are the same you previously used for plt.plot.

Result:

Adapt the same logic for Delay in order to get the errors for that variable, too.




回答2:


plt.errorbar() draws lineplots with error bars. It's parameters are quite similar to plt.plot(). The xlims need to be a bit wider to avoid the error bars being cut by the plot borders.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({'Time': ['D=0', 'D=2', 'D=5', 'D=X'],
                   'Latency': [74.92, 75.32, 79.64, 100],
                   'Delay': [18.2, 80, 82, 84]})
latency_min_max = np.array([(73.3, 76), (73.3, 80), (75, 83.3), (100, 100)]).T
latency_err = np.abs(latency_min_max - df['Latency'].to_numpy())
delay_min_max = np.array([(0, 50), (50, 100), (68, 90), (75, 90)]).T
delay_err = np.abs(delay_min_max - df['Delay'].to_numpy())

plt.errorbar('Time', 'Latency', yerr=latency_err, data=df, marker='s', capsize=2,
             color='black', markersize=4, linewidth=1, linestyle='--')
plt.errorbar('Time', 'Delay', yerr=delay_err, data=df,
             marker='o', capsize=4, color='black', markersize=4, linewidth=1, linestyle='-')
plt.legend()
plt.xlabel("Time")
plt.ylabel("Average Score (%)")
plt.ylim(0, 100)
plt.xlim(-0.2, 3.2)
plt.savefig('Fig2.png', dpi=300, bbox_inches='tight')
plt.show()

An alternative is to use plt.fill_between to create error bands:

plt.fill_between(df['Time'], latency_min_max[0, :], latency_min_max[1, :], color='red', alpha=0.2, label='Latency error')
plt.fill_between(df['Time'], delay_min_max[0, :], delay_min_max[1, :], color='blue', alpha=0.2, label='Delay error')




回答3:


You should use plt.errorbar instead of plt.plot, then assign the absolute value of the difference between the data points and the lower/upper limits as the lower/upper error values (numpy has convenient vectorization to do this). To avoid the caps of the error bars overlapping and which could be confusing, I would suggest using different colors and updating the legend.

From a presentation perspective, it would probably look nicer to have some whitespace around the axes so the data doesn't look cut off - you can set the plt.xlim and plt.ylim accordingly. Credit to @JohanC for doing this first.

import numpy as np
import pandas as pd
from pandas import DataFrame
import matplotlib.pyplot as plt
from matplotlib import pyplot as plt
import seaborn as sns

df = pd.DataFrame({'Time': ['D=0','D=2','D=5','D=X'],
    'Latency': [74.92, 75.32, 79.64, 100],
    'Delay': [18.2,80,82,84]
   })

latency_limits = np.array([[73.3,73.3,75,100],[76,80,83.3,100]])
delay_limits = np.array([[0,50,68,75],[50,100,90,90]])

latency_errors = abs(df.Latency.values - latency_limits)
delay_errors = abs(df.Delay.values - delay_limits)

yerr = np.array([[1,1,1,1],[5,5,5,5]])

fig = plt.figure()
Latency = plt.errorbar(
  x=df.Time, 
  y=df.Latency, 
  yerr=latency_errors, 
  capsize=4,
  marker='s', 
  color='red', 
  markersize=4, 
  linewidth=1, 
  linestyle='--')

Delay = plt.errorbar(
  x=df.Time, 
  y=df.Delay, 
  yerr=delay_errors,
  capsize=4,
  marker='o', 
  color='blue',  
  markersize=4, 
  linewidth=1,
  linestyle='-')

plt.legend((Latency, Delay),("Latency","Delay"))
plt.xlabel("Time")
plt.ylabel("Average Score (%)")
## widen both limits to give some whitespace to the plot
plt.ylim(-5, 105)
plt.xlim(-0.2, 3.2)
# plt.savefig('Fig2.png', dpi=300, bbox_inches='tight')
plt.margins(5,5)
plt.show()



来源:https://stackoverflow.com/questions/63419636/show-error-bar-in-multi-line-plot-using-matplotlib

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!