简体   繁体   中英

My figure legend colours do not match my graph line colours?

I'm trying to plot two lines on a graph and am struggling to match my legend colours to the graph line colours. When I try to assign colours to lines on the plot it only changes the legend and although it does alter the graph's line colours too they do not match the legend!

Here's the basis of my code.

import pandas as pd
import matplotlib.pyplot as plt

df_mated = pd.read_csv("file1.txt", sep='\t', header=0)   
df_mated['Average'] = df_mated.mean(axis=1)
df_mated['SEM'] = df_mated.loc[:, :'Average'].sem()
mated_E = df_mated['SEM'].tolist()
b = df_mated['Average'].tolist()
plot1, = plt.plot(x, b, 'r-')
plt.errorbar(x, b, xerr=None, yerr=mated_E)

df_unmated = pd.read_csv("file2.txt", sep='\t', header=0) 
df_unmated['Average'] = df_unmated.mean(axis=1)
df_unmated['SEM'] = df_unmated.loc[:, :'Average'].sem()
unmated_E = df_unmated['SEM'].tolist()
c = df_unmated['Average'].tolist()
plot2, = plt.plot(x, c, 'b-')
plt.errorbar(x, c, xerr=None, yerr=unmated_E)

plt.xlabel('Position')
plt.ylabel('Average Read Depth')
plt.legend([plot1,plot2],["Mated", "Unmated"])
plt.show()

Here's what I get: Output Graph

As you can see the colours do not match but more importantly the mated red line is definitely supposed to be the top line on the graph. I've verified this by printing the lists b and c so I am sure.

If I remove the 'r-' and 'b-' I get the following graph: Output Graph 2

Still not right...

I'm new to python and coding so let me know if you need any more information. Thanks for any help!

PS As you might be able to see my error bars also only work for half the graph as .sem() produces NaN for certain values in my pandas dataframe. I think this may be due to a division by 0 error as all my data are very small floats - but if you have any insights that would also be appreciated!

The errobar lines hide the lines you show in the legend. You can just remove the redundant plots and just plot the errobar (lines) in the respective color. So instead of

plot1, = plt.plot(x, b, 'r-')
plt.errorbar(x, b, xerr=None, yerr=mated_E)
# ...
plot2, = plt.plot(x, c, 'b-')
plt.errorbar(x, c, xerr=None, yerr=unmated_E)

use

plot1, _, _ = plt.errorbar(x, b, xerr=None, yerr=mated_E, color="r")
# ...
plot2, _, _ = plt.errorbar(x, c, xerr=None, yerr=unmated_E, color="b")

You are basically plotting the error bar over the inital line plot. As default the plt.errorbar is a line plot with error bar on each point.

# Gives a red line plot
plot1, = plt.plot(x, b, 'r-')
# Gives a '#1f77b4' (default first color) line plot with error bars
plt.errorbar(x, b, xerr=None, yerr=mated_E)

Giving this blue-ish line that you have. The same can be applied to the second plot.

Just add a linestyle to deactivate the line connecting the points for the errobar with ls=''

The correction below should work:

import pandas as pd
import matplotlib.pyplot as plt

df_mated = pd.read_csv("file1.txt", sep='\t', header=0)   
df_mated['Average'] = df_mated.mean(axis=1)
df_mated['SEM'] = df_mated.loc[:, :'Average'].sem()
mated_E = df_mated['SEM'].tolist()
b = df_mated['Average'].tolist()
plot1, = plt.plot(x, b, 'r-')
# Plot only the y-errorbar, not the line connecting the datapoint
plt.errorbar(x, b, xerr=None, yerr=mated_E, ls='')

df_unmated = pd.read_csv("file2.txt", sep='\t', header=0) 
df_unmated['Average'] = df_unmated.mean(axis=1)
df_unmated['SEM'] = df_unmated.loc[:, :'Average'].sem()
unmated_E = df_unmated['SEM'].tolist()
c = df_unmated['Average'].tolist()
plot2, = plt.plot(x, c, 'b-')
# Plot only the y-errorbar, not the line connecting the datapoint
plt.errorbar(x, c, xerr=None, yerr=unmated_E, ls='')

plt.xlabel('Position')
plt.ylabel('Average Read Depth')
plt.legend([plot1,plot2],["Mated", "Unmated"])
plt.show()

Try setting the labels when you call plot and remove the plt.plot lines, then just call plt.legend() without arguments.

plt.errorbar(x, b, xerr=None, yerr=mated_E, fmt='r-', label='Mated') 
plt.errorbar(x, c, xerr=None, yerr=unmated_E, fmt='b-', label='Unmated')
plt.legend()

What is happening is that the colors are correct, but hidden behind the errorbar plot. plt.errorbar plot both the line and the errors. Since you set the color on the first plot and not the second, the colors end up being different.

As for the error bars, check whether the values are all the same. In that case, the standard deviation will be zero.

You can also use seaborn which can potentially save you a lot of time ;-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM