Here's an example of what I mean:
import matplotlib.pyplot as plt
xdata = [5, 10, 15, 20, 25, 30, 35, 40]
ydata = [1, 3, 5, 7, 9, 11, 13, 15]
yerr_dat = 0.5
plt.figure()
plt.plot(xdata, ydata, 'go--', label='Data', zorder=1)
plt.errorbar(xdata, ydata, yerr = yerr_dat, zorder=2, fmt='ko')
plt.legend()
plt.show()
which will plot this:
I don't want the error points and the None label in the legend, how can I take those out?
I'm using Canopy in its version 1.0.1.1190.
Edit
After trying Joe's solution with this code:
import matplotlib.pyplot as plt
xdata = [5, 10, 15, 20, 25, 30, 35, 40]
ydata = [1, 3, 5, 7, 9, 11, 13, 15]
yerr_dat = 0.5
value = 20
plt.figure()
scatt = plt.plot(xdata, ydata, 'go--', label='Data', zorder=1)
hline = plt.hlines(y=5, xmin=0, xmax=40)
vline = plt.vlines(x=20, ymin=0, ymax=15)
plt.errorbar(xdata, ydata, yerr = yerr_dat, zorder=2, fmt='ko')
plt.legend([scatt, vline, hline], ['Data', 'Horiz line', 'Verti line = %d' % value], fontsize=12)
plt.show()
I get this warning:
/home/gabriel/Canopy/appdata/canopy-1.0.0.1160.rh5-x86/lib/python2.7/site-packages/matplotlib/legend.py:628: UserWarning: Legend does not support [<matplotlib.lines.Line2D object at 0xa09a28c>]
Use proxy artist instead.
http://matplotlib.sourceforge.net/users/legend_guide.html#using-proxy-artist
(str(orig_handle),))
and this output:
where the first label is not showing for some reason. Ideas?
Edit 2
Turns out I was missing a comma in the line:
scatt, = plt.plot(xdata, ydata, 'go--', label='Data', zorder=1)
After adding it everything worked like a charm. Thanks Joe!
On newer versions of matplotlib, what you're wanting is the default behavior. Only artists with an explicitly assigned label will appear in the legend.
However, it's easy to control what's displayed in the legend. Just pass in only the artists you'd like to label:
import matplotlib.pyplot as plt
xdata = [5, 10, 15, 20, 25, 30, 35, 40]
ydata = [1, 3, 5, 7, 9, 11, 13, 15]
yerr_dat = 0.5
plt.figure()
dens = plt.plot(xdata, ydata, 'go--', zorder=1)
plt.errorbar(xdata, ydata, yerr = yerr_dat, zorder=2, fmt='ko')
plt.legend(dens, ['Density Profile'])
plt.show()
Alternately, you could specify label='_nolegend_' for the errorbar plot, but I don't know what versions of matplotlib support that, and passing in explicit lists of artists and labels will work for any version.
If you'd like to add other artists:
import matplotlib.pyplot as plt
xdata = [5, 10, 15, 20, 25, 30, 35, 40]
ydata = [1, 3, 5, 7, 9, 11, 13, 15]
yerr_dat = 0.5
plt.figure()
# Note the comma! We're unpacking the tuple that `plot` returns...
dens, = plt.plot(xdata, ydata, 'go--', zorder=1)
hline = plt.axhline(5)
plt.errorbar(xdata, ydata, yerr = yerr_dat, zorder=2, fmt='ko')
plt.legend([dens, hline], ['Density Profile', 'Ceiling'], loc='upper left')
plt.show()
Related
I want to combine multiple grouped bar charts into one figure, as the image below shows.
grouped bar charts in a single figure
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
labels = ['G1', 'G2', 'G3']
yesterday_test1_mean = [20, 12, 23]
yesterday_test2_mean = [21, 14, 25]
today_test1_mean = [18, 10, 12]
today_test2_mean = [13, 13, 9]
Firstly I created each grouped bar chart by plt.subplots()
x = np.arange(len(labels))
width = 0.3
fig1, ax = plt.subplots()
rects1 = ax.bar(x-width/2, yesterday_test1_mean, width)
rects2 = ax.bar(x+width/2, yesterday_test2_mean, width)
fig2, ax = plt.subplots()
rects3 = ax.bar(x-width/2, today_test1_mean, width)
rects4 = ax.bar(x+width/2, today_test2_mean, width)
Then, I used add_subplot in an attempt to treat fig1 and fig2 as new axes in a new figure.
fig_all = plt.figure()
fig1 = fig_all.add_subplot(1,2,1)
fig2 = fig_all.add_subplot(1,2,2)
fig_all.tight_layout()
plt.show()
But it didn't work. How can I combined several grouped bar charts into a single figure?
Thanks in advance.
Well, I tried something. Here's a rough result. Only thing I changed is that rather using axes, I am just using subplot as I learned over time. So with fig and axes as output, there must be a way too. But this is all I've ever used. I've not added the legend and title yet, but I guess you can try it on your own too.
Here's the code with just small change:
import matplotlib.pyplot as plt
import numpy as np
labels = ['G1', 'G2', 'G3']
yesterday_test1_mean = [20, 12, 23]
yesterday_test2_mean = [21, 14, 25]
today_test1_mean = [18, 10, 12]
today_test2_mean = [13, 13, 9]
x = np.arange(len(labels))
width = 0.3
plt.figure(figsize=(12,5))
plt.subplot(121)
plt.bar(x-width/2, yesterday_test1_mean, width)
plt.bar(x+width/2, yesterday_test2_mean, width)
plt.subplot(122)
plt.bar(x-width/2, today_test1_mean, width)
plt.bar(x+width/2, today_test2_mean, width)
plt.show()
And here's your initial result:
While you see the result and try some stuff on your own, let me try to add the labels and legend to it as well as you've provided in the sample image.
Edit: The final output
So here it is, the exact thing you're looking for:
Code:
import matplotlib.pyplot as plt
import numpy as np
labels = ['G1', 'G2', 'G3']
yesterday_test1_mean = [20, 12, 23]
yesterday_test2_mean = [21, 14, 25]
today_test1_mean = [18, 10, 12]
today_test2_mean = [13, 13, 9]
x = np.arange(len(labels))
width = 0.3
plt.figure(figsize=(12,5))
plt.subplot(121)
plt.title('Yesterday', fontsize=18)
plt.bar(x-width/2, yesterday_test1_mean, width, label='test1', hatch='//', color=np.array((199, 66, 92))/255)
plt.bar(x+width/2, yesterday_test2_mean, width, label='test2', color=np.array((240, 140, 58))/255)
plt.xticks([0,1,2], labels, fontsize=15)
plt.subplot(122)
plt.title('Today', fontsize=18)
plt.bar(x-width/2, today_test1_mean, width, hatch='//', color=np.array((199, 66, 92))/255)
plt.bar(x+width/2, today_test2_mean, width, color=np.array((240, 140, 58))/255)
plt.xticks([0,1,2], labels, fontsize=15)
plt.figlegend(loc='upper right', ncol=1, labelspacing=0.5, fontsize=14, bbox_to_anchor=(1.11, 0.9))
plt.tight_layout(w_pad=6)
plt.show()
There is two method for doing subplots that you might try to combine accidentally: plt.subplot and plt.subplots.
Here is example how you can use plt.subplots to create two bar charts.
import numpy as np
import matplotlib.pyplot as plt
labels = ['G1', 'G2', 'G3']
yesterday_test1_mean = [20, 12, 23]
yesterday_test2_mean = [21, 14, 25]
today_test1_mean = [18, 10, 12]
today_test2_mean = [13, 13, 9]
x = np.arange(len(labels))
width = 0.3
fig, (ax1, ax2) = plt.subplots(1, 2)
ax1.bar(x-width/2, yesterday_test1_mean, width)
ax1.bar(x+width/2, yesterday_test2_mean, width)
ax2.bar(x-width/2, today_test1_mean, width)
ax2.bar(x+width/2, today_test2_mean, width)
plt.show()
There is only little changes on your code. You can add labels with:
ax1.set_title('Yesterday')
ax2.set_title('Today')
ax1.set_xticks(x)
ax1.set_xticklabels(labels)
ax2.set_xticks(x)
ax2.set_xticklabels(labels)
I found the following barplot on the following website: http://ndaratha.blogspot.com/2015/03/grouped-bar-plot
According to the website, it corresponds to the following code
import matplotlib.pyplot as plt
# Input data; groupwise
green_data = [16, 23, 22, 21, 13, 11, 18, 15]
blue_data = [ 3, 3, 0, 0, 5, 5, 3, 3]
red_data = [ 6, 6, 6, 0, 0, 0, 0, 0]
black_data = [25, 32, 28, 21, 18, 16, 21, 18]
labels = ['XI', 'XII', 'XIII', 'XIV', 'XV', 'XVI', 'XVII', 'XVIII']
# Setting the positions and width for the bars
pos = list(range(len(green_data)))
width = 0.15 # the width of a bar
# Plotting the bars
fig, ax = plt.subplots(figsize=(10,6))
bar1=plt.bar(pos, green_data, width,
alpha=0.5,
color='w',
hatch='x', # this one defines the fill pattern
label=labels[0])
plt.bar([p + width for p in pos], blue_data, width,
alpha=0.5,
color='w',
hatch='o',
label=labels[1])
plt.bar([p + width*2 for p in pos], red_data, width,
alpha=0.5,
color='k',
hatch='',
label=labels[2])
plt.bar([p + width*3 for p in pos], black_data, width,
alpha=0.5,
color='w',hatch='*',
label=labels[3])
# Setting axis labels and ticks
ax.set_ylabel('Number of Switching')
ax.set_xlabel('Strategy')
ax.set_title('Grouped bar plot')
ax.set_xticks([p + 1.5 * width for p in pos])
ax.set_xticklabels(labels)
# Setting the x-axis and y-axis limits
plt.xlim(min(pos)-width, max(pos)+width*5)
plt.ylim([0, max(green_data + blue_data + red_data) * 1.5])
# Adding the legend and showing the plot
plt.legend(['OLTC', 'SVC', 'SC', 'OLTC+SC+SVC'], loc='upper right')
plt.grid()
plt.show()
But when I try running the code, I get the following output
Does anyone know what I'm doing wrong or what I should do to get the desired output?
You need to add edgecolor = "k" in your plt.bar() code which gives black colors to the bar edges, and you can get the barplot you want.
When you add edgecolor = "k", code is as follows,
import matplotlib.pyplot as plt
# Input data; groupwise
green_data = [16, 23, 22, 21, 13, 11, 18, 15]
blue_data = [ 3, 3, 0, 0, 5, 5, 3, 3]
red_data = [ 6, 6, 6, 0, 0, 0, 0, 0]
black_data = [25, 32, 28, 21, 18, 16, 21, 18]
labels = ['XI', 'XII', 'XIII', 'XIV', 'XV', 'XVI', 'XVII', 'XVIII']
# Setting the positions and width for the bars
pos = list(range(len(green_data)))
width = 0.15 # the width of a bar
# Plotting the bars
fig, ax = plt.subplots(figsize=(10,6))
bar1=plt.bar(pos, green_data, width,
alpha=0.5,
color='w',
hatch='x', # this one defines the fill pattern
label=labels[0],edgecolor='black')
plt.bar([p + width for p in pos], blue_data, width,
alpha=0.5,
color='w',
hatch='o',
label=labels[1],edgecolor='black')
plt.bar([p + width*2 for p in pos], red_data, width,
alpha=0.5,
color='k',
hatch='',
label=labels[2],edgecolor='black')
plt.bar([p + width*3 for p in pos], black_data, width,
alpha=0.5,
color='w',hatch='*',
label=labels[3],edgecolor='black')
# Setting axis labels and ticks
ax.set_ylabel('Number of Switching')
ax.set_xlabel('Strategy')
ax.set_title('Grouped bar plot')
ax.set_xticks([p + 1.5 * width for p in pos])
ax.set_xticklabels(labels)
# Setting the x-axis and y-axis limits
plt.xlim(min(pos)-width, max(pos)+width*5)
plt.ylim([0, max(green_data + blue_data + red_data) * 1.5])
# Adding the legend and showing the plot
plt.legend(['OLTC', 'SVC', 'SC', 'OLTC+SC+SVC'], loc='upper right')
plt.grid()
plt.show()
Here is a simple plot:
1) How to disable the ticks?
2) How to reduce their number?
Here is a sample code:
from pylab import *
import numpy as np
x = [5e-05, 5e-06, 5e-07, 5e-08, 5e-09, 5e-10]
y = [-13, 14, 100, 120, 105, 93]
def myfunc(x,p):
sl,yt,yb,ec=p
y = yb + (yt-yb)/(1+np.power(10, sl*(np.log10(x)-np.log10(ec))))
return y
xp = np.power(10, np.linspace(np.log10(min(x)/10), np.log10(max(x)*10), 100))
pxp=myfunc(xp, [1,100,0,1e-6])
subplot(111,axisbg="#dfdfdf")
plt.plot(x, y, '.', xp, pxp, 'g-', linewidth=1)
plt.xscale('log')
plt.grid(True,ls="-", linewidth=0.4, color="#ffffff", alpha=0.5)
plt.draw()
plt.show()
Which produces:
plt.minorticks_off()
Turns em off!
To change the number of them/position them, you can use the subsx parameter. like this:
plt.xscale('log', subsx=[2, 3, 4, 5, 6, 7, 8, 9])
From the docs:
subsx/subsy: Where to place the subticks between each major tick.
Should be a sequence of integers. For example, in a log10 scale: [2,
3, 4, 5, 6, 7, 8, 9]
will place 8 logarithmically spaced minor ticks between each major
tick.
Calling plt.minorticks_off() will apply this to the current axis. (The function is actually a wrapper to gca().minorticks_off().)
You can also apply this to an individual axis in the same way:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.minorticks_off()
from pylab import *
import numpy as np
x = [5e-05, 5e-06, 5e-07, 5e-08, 5e-09, 5e-10]
y = [-13, 14, 100, 120, 105, 93]
def myfunc(x,p):
sl,yt,yb,ec=p
y = yb + (yt-yb)/(1+np.power(10, sl*(np.log10(x)-np.log10(ec))))
return y
xp = np.power(10, np.linspace(np.log10(min(x)/10), np.log10(max(x)*10), 100))
pxp=myfunc(xp, [1,100,0,1e-6])
ax=subplot(111,axisbg="#dfdfdf")
plt.plot(x, y, '.', xp, pxp, 'g-', linewidth=1)
plt.xscale('log')
plt.grid(True,ls="-", linewidth=0.4, color="#ffffff", alpha=0.5)
plt.minorticks_off() # turns off minor ticks
plt.draw()
plt.show()
Trying to make the pie larger. Looking at the docs, and other places, it says to set the radius. It seems no matter which value I put in the radius there's no increase. I'm posting the full code and the image it generates.
import matplotlib.pyplot as plt
def autopct_generator(limit):
"""Remove percent on small slices."""
def inner_autopct(pct):
return ('%.2f%%' % pct) if pct > limit else ''
return inner_autopct
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs', 'Test', 'Test2', 'Test3', \
'Test4', 'Test5', 'Test6', 'Test7', 'Test8', 'Test9', 'Test10', \
'Test11', 'Test12', 'Test13', 'Test14'
sizes = [15, 30, 45, 10, 10, 24, 13, 18, 28, 20, 13, 15, 5, 1, 18, 10,
10, 10]
NUM_COLORS = len(sizes)
fig1, ax1 = plt.subplots(figsize=(6, 5))
# set color theme
# https://matplotlib.org/api/pyplot_summary.html#colors-in-matplotlib
theme = plt.get_cmap('bwr')
ax1.set_color_cycle([theme(
1. * i / NUM_COLORS) for i in range(NUM_COLORS)])
box = ax1.get_position()
ax1.set_position([box.x0, box.y0, box.width * 1.3, box.height])
_, _, autotexts = ax1.pie(
sizes, autopct=autopct_generator(7), startangle=90, radius=1.8 * 1000)
for autotext in autotexts:
autotext.set_weight('bold')
ax1.axis('equal')
total = sum(sizes)
plt.legend(
loc='upper left',
labels=['%s, %1.1f%%' % (
l, (float(s) / total) * 100) for l, s in zip(labels, sizes)],
prop={'size': 12},
bbox_to_anchor=(0.0, 1),
bbox_transform=fig1.transFigure
)
# fig1.set_size_inches(18.5, 10.5)
fig1.savefig('chart.png')
If you turn on the axes of the pie chart,
ax.pie(..., radius=1800, frame=True)
you'll see that the radius is indeed applied correctly.
If you want to let the axes appear larger in the plot, you may use the subplot parameters.
fig.subplots_adjust(left,bottom,right,top)
Example code:
import matplotlib.pyplot as plt
sizes = [15, 30, 45, 10, 10, 24, 13, 18, 28, 20, 13, 15, 5, 1, 18, 10,
10, 10]
labels = ["Frogs %s" % i for i in sizes]
fig1, ax1 = plt.subplots(figsize=(6, 5))
fig1.subplots_adjust(0.3,0,1,1)
theme = plt.get_cmap('bwr')
ax1.set_prop_cycle("color", [theme(1. * i / len(sizes)) for i in range(len(sizes))])
_, _ = ax1.pie(sizes, startangle=90)
ax1.axis('equal')
total = sum(sizes)
plt.legend(
loc='upper left',
labels=['%s, %1.1f%%' % (
l, (float(s) / total) * 100) for l, s in zip(labels, sizes)],
prop={'size': 11},
bbox_to_anchor=(0.0, 1),
bbox_transform=fig1.transFigure
)
plt.show()
I am trying to draw two data lines with error bars, each having the same color as the data line. However, I get another thin line with a color I have not specified in each data line when I add an error bar.
Also, I would like to make the caps of the error bars thicker but the option capthick is not valid here.
Could anybody please help me fix these issues?
This is my code.
import matplotlib.pyplot as plt
from pylab import *
import numpy as np
xaxis = [1, 2, 3]
mean1 = [1,2,3.6]
se1 = [0.2, 0.5, 0.9]
mean2 = [10, 29, 14]
se2 = [3, 4, 2]
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_xlabel('X', fontsize = 16)
ax.set_ylabel('Y', fontsize = 16)
ax.axis([0, 5, 0, 35])
ax.plot(xaxis, mean1, 'r--', linewidth = 4)
ax.errorbar(xaxis, mean1, yerr = se1, ecolor = 'r', elinewidth = 2, capsize = 5)
ax.plot(xaxis, mean2, 'b--', linewidth = 4)
ax.errorbar(xaxis, mean2, yerr = se2, ecolor = 'b', elinewidth = 2, capsize = 5)
plt.show()
The extra thin line is coming from the errorbar() call.
errorbar will draw a line too, what you're doing is changing the colour of the error bars, but not the actual lines (hence it using the standard matplotlib first two colours, blue and green.
it's all in the documentaion, here.
To achieve what you want, you only need to use the errorbar() function;
This does what you want i think, maybe jsut tweak the numbers a bit.
import matplotlib.pyplot as plt
from pylab import *
import numpy as np
xaxis = [1, 2, 3]
mean1 = [1,2,3.6]
se1 = [0.2, 0.5, 0.9]
mean2 = [10, 29, 14]
se2 = [3, 4, 2]
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_xlabel('X', fontsize = 16)
ax.set_ylabel('Y', fontsize = 16)
ax.axis([0, 5, 0, 35])
linestyle = {"linestyle":"--", "linewidth":4, "markeredgewidth":5, "elinewidth":5, "capsize":10}
ax.errorbar(xaxis, mean1, yerr = se1, color="r", **linestyle)
ax.errorbar(xaxis, mean2, yerr = se2, color="b", **linestyle)
plt.show()
I put the common line style arguments into a dict which gets unpacked.