Is there any way to plot a bar plot using matplotlib using data directly from a dict?
My dict looks like this:
D = {u'Label1':26, u'Label2': 17, u'Label3':30}
I was expecting
fig = plt.figure(figsize=(5.5,3),dpi=300)
ax = fig.add_subplot(111)
bar = ax.bar(D,range(1,len(D)+1,1),0.5)
to work, but it does not.
Here is the error:
>>> ax.bar(D,range(1,len(D)+1,1),0.5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python2.7/site-packages/matplotlib/axes.py", line 4904, in bar
self.add_patch(r)
File "/usr/local/lib/python2.7/site-packages/matplotlib/axes.py", line 1570, in add_patch
self._update_patch_limits(p)
File "/usr/local/lib/python2.7/site-packages/matplotlib/axes.py", line 1588, in _update_patch_limits
xys = patch.get_patch_transform().transform(vertices)
File "/usr/local/lib/python2.7/site-packages/matplotlib/patches.py", line 580, in get_patch_transform
self._update_patch_transform()
File "/usr/local/lib/python2.7/site-packages/matplotlib/patches.py", line 576, in _update_patch_transform
bbox = transforms.Bbox.from_bounds(x, y, width, height)
File "/usr/local/lib/python2.7/site-packages/matplotlib/transforms.py", line 786, in from_bounds
return Bbox.from_extents(x0, y0, x0 + width, y0 + height)
TypeError: coercing to Unicode: need string or buffer, float found
You can do it in two lines by first plotting the bar chart and then setting the appropriate ticks:
import matplotlib.pyplot as plt
D = {u'Label1':26, u'Label2': 17, u'Label3':30}
plt.bar(range(len(D)), list(D.values()), align='center')
plt.xticks(range(len(D)), list(D.keys()))
# # for python 2.x:
# plt.bar(range(len(D)), D.values(), align='center') # python 2.x
# plt.xticks(range(len(D)), D.keys()) # in python 2.x
plt.show()
Note that the penultimate line should read plt.xticks(range(len(D)), list(D.keys())) in python3, because D.keys() returns a generator, which matplotlib cannot use directly.
It's a little simpler than most answers here suggest:
import matplotlib.pyplot as plt
D = {u'Label1':26, u'Label2': 17, u'Label3':30}
plt.bar(*zip(*D.items()))
plt.show()
For future reference, the above code does not work with Python 3. For Python 3, the D.keys() needs to be converted to a list.
import matplotlib.pyplot as plt
D = {u'Label1':26, u'Label2': 17, u'Label3':30}
plt.bar(range(len(D)), D.values(), align='center')
plt.xticks(range(len(D)), list(D.keys()))
plt.show()
Why not just:
names, counts = zip(*D.items())
plt.bar(names, counts)
The best way to implement it using matplotlib.pyplot.bar(range, height, tick_label) where the range provides scalar values for the positioning of the corresponding bar in the graph. tick_label does the same work as xticks(). One can replace it with an integer also and use multiple plt.bar(integer, height, tick_label). For detailed information please refer the documentation.
import matplotlib.pyplot as plt
data = {'apple': 67, 'mango': 60, 'lichi': 58}
names = list(data.keys())
values = list(data.values())
#tick_label does the some work as plt.xticks()
plt.bar(range(len(data)),values,tick_label=names)
plt.savefig('bar.png')
plt.show()
Additionally the same plot can be generated without using range(). But the problem encountered was that tick_label just worked for the last plt.bar() call. Hence xticks() was used for labelling:
data = {'apple': 67, 'mango': 60, 'lichi': 58}
names = list(data.keys())
values = list(data.values())
plt.bar(0,values[0],tick_label=names[0])
plt.bar(1,values[1],tick_label=names[1])
plt.bar(2,values[2],tick_label=names[2])
plt.xticks(range(0,3),names)
plt.savefig('fruit.png')
plt.show()
I often load the dict into a pandas DataFrame then use the plot function of the DataFrame.
Here is the one-liner:
pandas.DataFrame(D, index=['quantity']).plot(kind='bar')
Why not just:
import seaborn as sns
sns.barplot(list(D.keys()), list(D.values()))
Related
I am trying to produce a bar plot with a line of regression. I am trying to follow a previous suggestion for the same problem but get an error message that I am unable to overcome. My script is as follows:
import seaborn.apionly as sns
import matplotlib.pyplot as plt
import pandas as pd
sns.set(style="white", context="score")
data = {'Days': ['5', '10', '15', '20'],
'Impact': ['33.7561', '30.6281', '29.5748', '29.0482']
}
a = pd.DataFrame (data, columns = ['Days','Impact'])
print (a)
ax = sns.barplot(data=a, x=a.Days, y=a.Impact, color='lightblue' )
# put bars in background:
for c in ax.patches:
c.set_zorder(0)
# plot regplot with numbers 0,..,len(a) as x value
sns.regplot(x=np.arange(0,len(a)), y=a.Impact, ax=ax)
sns.despine(offset=10, trim=False)
ax.set_ylabel("")
ax.set_xticklabels(['5', '10','15','20'])
plt.show()
The error message I get is:
Traceback (most recent call last):
File "C:\Users\david\AppData\Local\Programs\Spyder\pkgs\IPython\core\async_helpers.py", line 68, in _pseudo_sync_runner
coro.send(None)
File "C:\Users\david\AppData\Local\Programs\Spyder\pkgs\IPython\core\interactiveshell.py", line 3162, in run_cell_async
self.displayhook.exec_result = result
File "C:\Users\david\AppData\Local\Programs\Spyder\pkgs\traitlets\traitlets.py", line 604, in __set__
self.set(obj, value)
File "C:\Users\david\AppData\Local\Programs\Spyder\pkgs\traitlets\traitlets.py", line 578, in set
new_value = self._validate(obj, value)
File "C:\Users\david\AppData\Local\Programs\Spyder\pkgs\traitlets\traitlets.py", line 610, in _validate
value = self.validate(obj, value)
File "C:\Users\david\AppData\Local\Programs\Spyder\pkgs\traitlets\traitlets.py", line 1842, in validate
if isinstance(value, self.klass):
TypeError: isinstance() arg 2 must be a type or tuple of types
ERROR! Session/line number was not unique in database. History logging moved to new session 54
but I am not sure what this means. Can anyone help?
Please ensure you supply int or float in the df
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
data = {'Days': [5, 10, 15, 20],
'Impact': [33.7561, 30.6281, 29.5748, 29.0482]
}
a = pd.DataFrame (data, columns = ['Days','Impact'])
print (a)
ax = sns.barplot(data=a, x='Days', y='Impact', color='lightblue' )
# put bars in background:
for c in ax.patches:
c.set_zorder(0)
# plot regplot with numbers 0,..,len(a) as x value
ax = sns.regplot(x=np.arange(0,len(a)), y=a['Impact'], marker="+")
sns.despine(offset=10, trim=False)
ax.set_ylabel("")
ax.set_xticklabels(['5', '10','15','20'])
plt.show()
I'm trying to create a map visualization using the basemap module in Python 3.0 but when I try to plot this figure I get the TypeError:
TypeError: input must be an array, list, tuple or scalar
My code looks like this:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
data = pd.ExcelFile('C:\\Users\\...xlsx')
data_input = pd.read_excel(data, 'Sheet2')
# Extract the data we're interested in
lat = data_input['value1'].values
lon = data_input['value2'].values
capacity = data_input['value3'].values
# 1. Draw the map background
fig = plt.figure(figsize=(8, 8))
m = Basemap(projection='lcc', resolution='h',
lat_0=31.1351682, lon_0=-99.3350553,
width=1.3E6, height=1.25E6)
m.shadedrelief()
m.drawcoastlines(color='gray')
m.drawcountries(color='gray')
m.drawstates(color='gray')
# 2. scatter city data, with color reflecting population
# and size reflecting area
m.scatter(lon, lat, latlon=True,
c=np.log10(capacity), s=capacity,
cmap='Reds', alpha=0.5)
I've tried changing all the inputs to data_input.values, data_input.to_list(), list(data_input) and just using the default pandas Series.
The error traceback occurs here:
File "<ipython-input-6-3a66206674c7>", line 3, in <module>
cmap='Reds', alpha=0.5)
File "C:\Users\...Continuum\anaconda3\lib\site-packages\mpl_toolkits\basemap\__init__.py", line 566, in with_transform
x, y = self(x,y)
File "C:\Users\...\Continuum\anaconda3\lib\site-packages\mpl_toolkits\basemap\__init__.py", line 1191, in __call__
xout,yout = self.projtran(x,y,inverse=inverse)
File "C:\Users\...\Continuum\anaconda3\lib\site-packages\mpl_toolkits\basemap\proj.py", line 288, in __call__
outx,outy = self._proj4(x, y, inverse=inverse)
File "C:\Users\...\Continuum\anaconda3\lib\site-packages\pyproj\__init__.py", line 397, in __call__
inx, xisfloat, xislist, xistuple = _copytobuffer(lon)
File "C:\Users\...\Continuum\anaconda3\lib\site-packages\pyproj\__init__.py", line 652, in _copytobuffer
raise TypeError('input must be an array, list, tuple or scalar')
No matter what form it gets it doesn't work. What am I missing here?
There are several way to make a legend with matplotlib. May be the simpler way could be:
>>> line_up, = plt.plot([1,2,3], label='Up')
>>> line_down, = plt.plot([3,2,1], label='Down')
>>> plt.legend()
<matplotlib.legend.Legend object at 0x7f527f10ca58>
>>> plt.show()
One other way could be:
>>> line_up, = plt.plot([1,2,3])
>>> line_down, = plt.plot([3,2,1])
>>> plt.legend((line_up, line_down), ('Up', 'Down'))
<matplotlib.legend.Legend object at 0x7f527eea92e8>
>>> plt.show()
This last way seems to work only with objects supporting iteration:
>>> line_up, = plt.plot([1,2,3])
>>> plt.legend((line_up), ('Up'))
/usr/lib64/python3.4/site-packages/matplotlib/cbook.py:137: MatplotlibDeprecationWarning: The "loc" positional argument to legend is deprecated. Please use the "loc" keyword instead.
warnings.warn(message, mplDeprecation, stacklevel=1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python3.4/site-packages/matplotlib/pyplot.py", line 3519, in legend
ret = gca().legend(*args, **kwargs)
File "/usr/lib64/python3.4/site-packages/matplotlib/axes/_axes.py", line 496, in legend
in zip(self._get_legend_handles(handlers), labels)]
TypeError: zip argument #2 must support iteration
If I want use absolutely the second way with only one curve ... Hown can I do ?
I believe the reason for this is to define a one item tuple, you would use the syntax (line_up,). Note the trailing comma.
import matplotlib.pyplot as plt
line_up, = plt.plot([1,2,3])
plt.legend((line_up,), ('Up',))
plt.show()
You could also use a list if you would rather not include the trailing comma. For example:
import matplotlib.pyplot as plt
line_up, = plt.plot([1,2,3], label='my graph')
plt.legend(handles=[line_up])
plt.show()
Here is my code:
import matplotlib.pyplot as plt
plt.figure(1) # the first figure
plt.subplot(211) # the first subplot in the first figure
plt.plot([1, 2, 3])
plt.subplot(212) # the second subplot in the first figure
plt.plot([4, 5, 6])
plt.figure(2) # a second figure
plt.plot([4, 5, 6]) # creates a subplot(111) by default
plt.text(.5,1.5,'211',figure = 211) #tring to add text in previous subplot
plt.figure(1) # figure 1 current; subplot(212) still current
plt.subplot(211) # make subplot(211) in figure1 current
plt.title('Easy as 1, 2, 3') # subplot 211 title
The error:
Traceback (most recent call last):
File "C:/Users/ezhou/Desktop/python/test3.py", line 11, in <module>
plt.text(.5,1.5,'211',figure = 211)
File "C:\Python27\lib\site-packages\matplotlib\pyplot.py", line 3567, in text
ret = gca().text(x, y, s, fontdict=fontdict, withdash=withdash, **kwargs)
File "C:\Python27\lib\site-packages\matplotlib\axes\_axes.py", line 619, in text
self._add_text(t)
File "C:\Python27\lib\site-packages\matplotlib\axes\_base.py", line 1720, in _add_text
self._set_artist_props(txt)
File "C:\Python27\lib\site-packages\matplotlib\axes\_base.py", line 861, in _set_artist_props
a.set_figure(self.figure)
File "C:\Python27\lib\site-packages\matplotlib\artist.py", line 640, in set_figure
raise RuntimeError("Can not put single artist in "
RuntimeError: Can not put single artist in more than one figure
I was trying to understand the kwargs 'figure' in class matplotlib.text.Text(), but it will always reply 'Can not put single artist in more than one figure'. So I was confused about how to use this 'figure' kwarg. Can anyone give me some advise? Thanks!
You shouldn't pass figure as a kwarg, instead use text method of a Figure (or Axes) instance. Example:
import matplotlib.pyplot as plt
fig1, fig2 = plt.figure(1), plt.figure(2)
sp1, sp2 = fig1.add_subplot(211), fig2.add_subplot(211)
sp1.plot([1, 2, 3])
sp2.plot([0, 1, 3])
fig1.text(.5, .3, 'whole figure')
sp2.text(.5, .5, 'subplot')
Please note that coordinates are relative (0, 1).
P.S if you find matplotlib needlessly complicated (as I do), you may wish to have a look at Plotly
I'm trying to plot the path of 15 different storms on a map in 15 different colors. The color of the path should depend on the name of the storm. For example if the storm's name is AUDREY, the color of the storm's path should be red on the map. Could some please help/point me in the right direction?
Here's the part of my code:
import numpy as np
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import csv, os, scipy
import pandas
from PIL import *
data = np.loadtxt('louisianastormb.csv',dtype=np.str,delimiter=',',skiprows=1)
'''print data'''
fig = plt.figure(figsize=(12,12))
ax = fig.add_axes([0.1,0.1,0.8,0.8])
m = Basemap(llcrnrlon=-100.,llcrnrlat=0.,urcrnrlon=-20.,urcrnrlat=57.,
projection='lcc',lat_1=20.,lat_2=40.,lon_0=-60.,
resolution ='l',area_thresh=1000.)
m.bluemarble()
m.drawcoastlines(linewidth=0.5)
m.drawcountries(linewidth=0.5)
m.drawstates(linewidth=0.5)
# Creates parallels and meridians
m.drawparallels(np.arange(10.,35.,5.),labels=[1,0,0,1])
m.drawmeridians(np.arange(-120.,-80.,5.),labels=[1,0,0,1])
m.drawmapboundary(fill_color='aqua')
color_dict = {'AUDREY': 'red', 'ETHEL': 'white', 'BETSY': 'yellow','CAMILLE': 'blue', 'CARMEN': 'green',
'BABE': 'purple', 'BOB': '#ff69b4', 'FREDERIC': 'black', 'ELENA': 'cyan', 'JUAN': 'magenta', 'FLORENCE': '#faebd7',
'ANDREW': '#2e8b57', 'GEORGES': '#eeefff', 'ISIDORE': '#da70d6', 'IVAN': '#ff7f50', 'CINDY': '#cd853f',
'DENNIS': '#bc8f8f', 'RITA': '#5f9ea0', 'IDA': '#daa520'}
# Opens data file witn numpy
'''data = np.loadtxt('louisianastormb.csv',dtype=np.str,delimiter=',',skiprows=0)'''
'''print data'''
colnames = ['Year','Name','Type','Latitude','Longitude']
data = pandas.read_csv('louisianastormb.csv', names=colnames)
names = list(data.Name)
lat = list(data.Latitude)
long = list(data.Longitude)
colorName = list(data.Name)
#print lat
#print long
lat.pop(0)
long.pop(0)
latitude= map(float, lat)
longitude = map(float, long)
x, y = m(latitude,longitude)
#Plots points on map
for colorName in color_dict.keys():
plt.plot(x,y,'-',label=colorName,color=color_dict[colorName], linewidth=2 )
lg = plt.legend()
lg.get_frame().set_facecolor('grey')
plt.title('20 Hurricanes with Landfall in Louisiana')
#plt.show()
plt.savefig('20hurpaths1.jpg', dpi=100)
Here's the error message that I keep getting is:
Traceback (most recent call last):
File "/home/mikey1/lstorms.py", line 51, in <module>
plt.plot(x,y,'y-',color=colors[names], linewidth=2 )
TypeError: unhashable type: 'list'
>>>
You're accessing the dictionary entries incorrectly. First off you do this names = list(data.Name). So names is of type lists. Then you call dictionary like this: color_dict[names]. The problem is not setting the colour but how you try to access the dictionary (list is not a valid key).
Change it to something like:
for colourName in color_dict.keys():
plt.plot(x,y,'y-',color=color_dict[colourName], linewidth=2 ) # You need to use different data for the data series here.
And it'll work.
Also, your error message reads plt.plot(x,y,'y-',color=colors[names], linewidth=2 ) but in your code you've got color=colors_dict[names]. Are you sure you posted the right code?