5

I am using Pandas and Matplotlib to create some plots. I want line plots with error bars on them. The code I am using currently looks like this

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

df = pd.DataFrame(index=[10,100,1000,10000], columns=['A', 'B', 'C', 'D', 'E', 'F'], data=np.random.rand(4,6))
df_yerr = pd.DataFrame(index=[10,100,1000,10000], columns=['A', 'B', 'C', 'D', 'E', 'F'], data=np.random.rand(4,6))

fig, ax = plt.subplots()
df.plot(yerr=df_yerr, ax=ax, fmt="o-", capsize=5)
ax.set_xscale("log")
plt.show()

With this code, I get 6 lines on a single plot (which is what I want). However, the error bars completely overlap, making the plot difficult to read.

Is there a way I could slightly shift the position of each point on the x-axis so that the error bars no longer overlap?

Here is a screenshot:

enter image description here

JNevens
  • 11,202
  • 9
  • 46
  • 72
  • Can you show a screenshot of the graph you get? – DavidG Dec 14 '17 at 10:02
  • @DavidG Hope this makes my question more clear. – JNevens Dec 14 '17 at 10:06
  • 2
    To get better help, please provide a [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve). In particular check out [How to make good reproducible pandas examples](https://stackoverflow.com/questions/20109391/how-to-make-good-reproducible-pandas-examples) – Diziet Asahi Dec 14 '17 at 10:23
  • You can shift the points and errorbars. But that would falsify the plot as points would not at the correct x position any more. Are you sure this is what you want to do? – ImportanceOfBeingErnest Dec 14 '17 at 11:13

2 Answers2

6

One way to achieve what you want is to plot the error bars 'by hand', but it is neither straight forward nor much better looking than your original. Basically, what you do is make pandas produce the line plot and then iterate through the data frame columns and do a pyplot errorbar plot for each of them such, that the index is slightly shifted sideways (in your case, with the logarithmic scale on the x axis, this would be a shift by a factor). In the error bar plots, the marker size is set to zero:

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

colors = ['red','blue','green','yellow','purple','black']

df = pd.DataFrame(index=[10,100,1000,10000], columns=['A', 'B', 'C', 'D', 'E', 'F'], data=np.random.rand(4,6))
df_yerr = pd.DataFrame(index=[10,100,1000,10000], columns=['A', 'B', 'C', 'D', 'E', 'F'], data=np.random.rand(4,6))

fig, ax = plt.subplots()
df.plot(ax=ax, marker="o",color=colors)

index = df.index
rows = len(index)
columns = len(df.columns)

factor = 0.95
for column,color in zip(range(columns),colors):
    y = df.values[:,column]
    yerr = df_yerr.values[:,column]
    ax.errorbar(
        df.index*factor, y, yerr=yerr, markersize=0, capsize=5,color=color,
        zorder = 10,
    )
    factor *= 1.02

ax.set_xscale("log")
plt.show()

As I said, the result is not pretty:

result of the code above

UPDATE

In my opinion a bar plot would be much more informative:

fig2,ax2 = plt.subplots()
df.plot(kind='bar',yerr=df_yerr, ax=ax2)
plt.show()

result of second piece of code

Thomas Kühn
  • 9,412
  • 3
  • 47
  • 63
  • I just like to point out that a bar-plot is usually inferior to a well composed scatter plot or box-plot (in conveying information). Likely many will say, and I agree, that the bar-plot is *visually* more appealing than the upper plot. However, this does not justify the choice of a bar-plot, as there are better options (visually and information wise). To add a bit of substance to this claim, see for example [here](https://genomicsclass.github.io/book/pages/plots_to_avoid.html). – Matthias Arras Apr 19 '21 at 10:14
  • @MatthiasArras I agree with you, there are better choices. Mind though, that we don't really know what the OP wanted to visualise and hence it is hard to know what the best plot type is to represent his data. – Thomas Kühn Apr 19 '21 at 14:52
-2

you can solve with alpha for examples

df.plot(yerr=df_yerr, ax=ax, fmt="o-", capsize=5,alpha=0.5)

You can also check this link for reference

Muhammad Faizan
  • 1,709
  • 1
  • 15
  • 37