'Why does Marker does not accept zipped objects in Matplotlib and how to correct it?

I'm trying to run the code shown below (which I obtained from this source) to introduce pie charts in a Baseman object.

import math
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap

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

def draw_pie(ax,ratios=[0.4,0.3,0.3], X=0, Y=0, size = 1000):
    N = len(ratios)

    xy = []

    start = 0.
    for ratio in ratios:
        x = [0] + np.cos(np.linspace(2*math.pi*start,2*math.pi*(start+ratio), 30)).tolist()
        y = [0] + np.sin(np.linspace(2*math.pi*start,2*math.pi*(start+ratio), 30)).tolist()
        xy1 = zip(x,y)
        xy.append(xy1)
        start += ratio

    for i, xyi in enumerate(xy):
        ax.scatter([X],[Y] , marker=(xyi,0), s=size, facecolor=colors[i] )
        #ax.scatter([X],[Y] , marker=(2,0), s=size, facecolor=colors[i] )

fig = plt.figure(figsize=(11.7,8.3))
#Custom adjust of the subplots
plt.subplots_adjust(left=0.05,right=0.95,top=0.90,bottom=0.05,wspace=0.15,hspace=0.05)
ax = plt.subplot(111)
#Let's create a basemap around Belgium
m = Basemap(resolution='i',projection='merc', llcrnrlat=49.0,urcrnrlat=52.0,llcrnrlon=1.,urcrnrlon=8.0,lat_ts=51.0)
m.drawcountries(linewidth=0.5)
m.drawcoastlines(linewidth=0.5)

X,Y = m(4.5,50.5)
draw_pie(ax,[0.5,0.25,0.25], X, Y,size=300)
plt.savefig('test.png')
plt.savefig('test.pdf')

However, the code as provided produces the following error.

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-180-1520446b93e5> in <module>
     27 
     28 X,Y = m(4.5,50.5)
---> 29 draw_pie(ax,[0.5,0.25,0.25], X, Y,size=300)
     30 plt.savefig('test.png')
     31 plt.savefig('test.pdf')

<ipython-input-180-1520446b93e5> in draw_pie(ax, ratios, X, Y, size)
     15 
     16     for i, xyi in enumerate(xy):
---> 17         ax.scatter([X],[Y] , marker=(xyi,0), s=size, facecolor=colors[i] )
     18 
     19 fig = plt.figure(figsize=(11.7,8.3))

~/opt/anaconda3/lib/python3.8/site-packages/matplotlib/__init__.py in inner(ax, data, *args, **kwargs)
   1445     def inner(ax, *args, data=None, **kwargs):
   1446         if data is None:
-> 1447             return func(ax, *map(sanitize_sequence, args), **kwargs)
   1448 
   1449         bound = new_sig.bind(ax, *args, **kwargs)

~/opt/anaconda3/lib/python3.8/site-packages/matplotlib/cbook/deprecation.py in wrapper(*inner_args, **inner_kwargs)
    409                          else deprecation_addendum,
    410                 **kwargs)
--> 411         return func(*inner_args, **inner_kwargs)
    412 
    413     return wrapper

~/opt/anaconda3/lib/python3.8/site-packages/matplotlib/axes/_axes.py in scatter(self, x, y, s, c, marker, cmap, norm, vmin, vmax, alpha, linewidths, verts, edgecolors, plotnonfinite, **kwargs)
   4471             marker_obj = marker
   4472         else:
-> 4473             marker_obj = mmarkers.MarkerStyle(marker)
   4474 
   4475         path = marker_obj.get_path().transformed(

~/opt/anaconda3/lib/python3.8/site-packages/matplotlib/markers.py in __init__(self, marker, fillstyle)
    226         self._marker_function = None
    227         self.set_fillstyle(fillstyle)
--> 228         self.set_marker(marker)
    229 
    230     def _recache(self):

~/opt/anaconda3/lib/python3.8/site-packages/matplotlib/markers.py in set_marker(self, marker)
    311         if not isinstance(marker, MarkerStyle):
    312             self._marker = marker
--> 313             self._recache()
    314 
    315     def get_path(self):

~/opt/anaconda3/lib/python3.8/site-packages/matplotlib/markers.py in _recache(self)
    239         self._capstyle = 'butt'
    240         self._filled = True
--> 241         self._marker_function()
    242 
    243     def __bool__(self):

~/opt/anaconda3/lib/python3.8/site-packages/matplotlib/markers.py in _set_tuple_marker(self)
    370         symstyle = marker[1]
    371         if symstyle == 0:
--> 372             self._path = Path.unit_regular_polygon(numsides)
    373             self._joinstyle = 'miter'
    374         elif symstyle == 1:

~/opt/anaconda3/lib/python3.8/site-packages/matplotlib/path.py in unit_regular_polygon(cls, numVertices)
    711         centered at (0, 0).
    712         """
--> 713         if numVertices <= 16:
    714             path = cls._unit_regular_polygons.get(numVertices)
    715         else:

TypeError: '<=' not supported between instances of 'zip' and 'int'

I was able to track down the problem to

ax.scatter([X],[Y] , marker=(xyi,0), s=size, facecolor=colors[i] )

xyi is the "shape" of a polygon that will emulate the pie piece in the pie chart, but this is not accepted by marker. If the xyi is replaced by a int (like in the commented line), the script will run with no errors, but of course, there will be no pie chart... Apparently, marker only accepts an integer in this position. Not a list or a zip (as it is the case now).

I have searched how this particular marker works, but cannot understand how it is intended to operate and therefore cannot correct the script to make it work. Is there a way to correct this error?



Solution 1:[1]

The source you provided was created in 2010. Matplotlib has changed a lot since then. Your draw_pie function can be replaced with this now:

def draw_pie(ax, ratios=[0.4, 0.3, 0.3], X=0, Y=0, size=1):
    ax.pie(ratios,center=(X, Y), radius=size, frame=True)

Your code should work with:

fig = plt.figure(figsize=(11.7,8.3))
#Custom adjust of the subplots
plt.subplots_adjust(left=0.05,right=0.95,top=0.90,bottom=0.05,wspace=0.15,hspace=0.05)
ax = plt.subplot(111)
#Let's create a basemap around Belgium
m = Basemap(resolution='i',projection='merc', llcrnrlat=49.0,urcrnrlat=52.0,llcrnrlon=1.,urcrnrlon=8.0,lat_ts=51.0)
m.drawcountries(linewidth=0.5)
m.drawcoastlines(linewidth=0.5)

X,Y = m(4.5,50.5)
draw_pie(ax,[0.5,0.25,0.25], X, Y,size=3)
plt.savefig('test.png')
plt.savefig('test.pdf')

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1