5
votes

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

2
Can you show a screenshot of the graph you get? - DavidG
@DavidG Hope this makes my question more clear. - JNevens
To get better help, please provide a Minimal, Complete, and Verifiable example. In particular check out How to make good reproducible pandas examples - Diziet Asahi
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

2 Answers

6
votes

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

-2
votes

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