Related
The goal for my code is to make a rough roadmap using the latitude and longitude of the exits on the pennsylvania turnpike drawing a line between each exit.
I am using a for loop to plot a line on the map every time it loops. This works if i hard code the latitude and longitude but as soon as i plug in my variables nothing gets plotted. Since the coordinates are in order I am just increasing the index every time it loops to get the next coordinates. I have printed the variables inside the loop and verified they have the desired value. I have tried putting the values in ordered pairs but the plot function didn't like me using nparrays. I'm not sure if there is something simple i am missing, but I appreciate any input.
import netCDF4 as nc
import numpy as np
import matplotlib.pyplot as plt
import cartopy
import cartopy.crs as ccrs
from datetime import datetime, timedelta
# Open the file for highway metadata to read csv data
highway_metadata = open('milestone3data.csv', 'r')
metafile = csv.reader(highway_metadata, delimiter = ',')
# Create empty lists with highway data
highway_loc = []
highway_name = []
highway_lat = []
highway_lon = []
highway_dist = []
# Loop to transfer the csv file's data into the lists
for i in metafile:
highway_loc.append(i[0])
highway_name.append(i[1])
highway_lat.append(float(i[2]))
highway_lon.append(float(i[3]))
highway_dist.append(i[4])
def road_map():
enhighway_lat = enumerate(highway_lat)
enhighway_lon = enumerate(highway_lon)
orthographic = ccrs.Orthographic()
platecarree = ccrs.PlateCarree()
proj = ccrs.Orthographic(central_longitude = -75, central_latitude = 41)
ax = plt.axes(projection=proj)
# Set up the background
ax.add_feature(cartopy.feature.COASTLINE)
ax.add_feature(cartopy.feature.STATES)
ax.set_extent((-85,-70,36,45),crs=ccrs.PlateCarree())
for i,j in enhighway_lat:
for k,l in enhighway_lon:
if i or k <= 30:
plt.plot([highway_lon[k], highway_lon[k+1]], [highway_lat[i], highway_lat[i+1]], color='black', linewidth=1, marker='o', markersize=3, transform=ccrs.PlateCarree())
plt.savefig('cartopytest7.png')
plt.show
road_map()
[This is my most recent output from the program][1]
[1]: https://i.stack.imgur.com/lgFrN.png
CSV file contents: (mile marker, name of exit, latitude, longitude, miles from beginning of turnpike)
2,Gateway (Ohio Connection),40.90419167,-80.47158333,1.43
10,New Castle,40.83018056,-80.34196111,10.7
13,Beaver Valley,40.8143,-80.307925,12.87
28,Cranberry,40.67983889,-80.09537778,28.47
30,Warrendale,40.65533889,-80.06116667,31
39,Butler Valley,40.60913611,-79.91924444,39.1
48,Allegheny Valley,40.542025,-79.81022222,47.73
57,Pittsburgh,40.43808889,-79.74956944,56.44
67,Irwin,40.31342778,-79.65476111,67.22
75,New Stanton,40.22173333,-79.59573333,75.39
91,Donegal,40.10915,-79.35231944,90.69
110,Somerset,40.02033056,-79.05208056,109.91
146,Bedford,40.05013889,-78.48615,145.5
161,Breezewood,39.98721667,-78.24472778,161.5
180,Fort Littleton,40.05010556,-77.93954444,179.44
189,Willow Hill,40.09674167,-77.78441389,188.59
201,Blue Mountain,40.15755278,-77.58403333,201.29
226,Carlisle,40.22814722,-77.14782222,226.54
236,Gettysburg Pike,40.19569444,-76.95665556,236.22
242,Harrisburg West Shore,40.21216667,-76.85765278,241.87
247,Harrisburg East,40.21501111,-76.78060278,247.38
266,Lebanon-Lancaster,40.22974444,-76.43095,266.45
286,Reading,40.21805,-76.05189167,286.09
298,Morgantown,40.15990278,-75.88311667,298.33
312,Downingtown,40.06838611,-75.66450278,311.93
320,SR29,40.07641667,-75.52881944,319.33
326,Valley Forge,40.09296667,-75.39591111,326.62
333,Norristown,40.11101111,-75.27921389,333.28
339,Fort Washington,40.13231944,-75.17092222,338.36
340,Virginia Dr,40.13854444,-75.16268611,339.8
343,Willow Grove,40.16166111,-75.11271111,342.91
351,Bensalem,40.13200278,-74.96229444,351.49
352,Street Rd,40.13150833,-74.96445,351.89
353,Neshaminy Falls,40.12916667,-74.94150278,352.67
Okay, based on the discussion above, see below for a solution.
Notes:
Am using pandas DataFames to easily work with the .csv file. the names field is the column names.
Am not using orthographic projection at all.
Am iterating through the list of highway exits one exit at a time; at each index, am extracting the current and next exits' data - am sure there's a more 'pythonic' way to do this, but this is readable at least.
edit: the final index in the loop is length-1
Update: Thanks to #SimonWillerton, I've removed the loop.
import netCDF4 as nc
import numpy as np
import matplotlib.pyplot as plt
import cartopy
import cartopy.crs as ccrs
import pandas as pd
def road_map():
# Open the file for highway metadata to read csv data
highway_metadata = pd.read_csv('milestone3data.csv', names=["loc", "name", "lat", "lon", "dist"])
proj = ccrs.PlateCarree(central_longitude = -75)
ax = plt.axes(projection=proj)
ax.add_feature(cartopy.feature.COASTLINE)
ax.add_feature(cartopy.feature.STATES)
ax.set_extent((-85,-70,36,45),crs=ccrs.PlateCarree())
plt.plot(highway_metadata['lon'], highway_metadata['lat'], \
color='black', linewidth=1, marker='o', markersize=3, transform=ccrs.PlateCarree())
plt.savefig('cartopytest7.png')
if __name__ == '__main__':
road_map()
This produces the following image:
And, based on this image of the Pennsylvania Turnpike from Wikipedia (source=https://commons.wikimedia.org/wiki/File:Pennsylvania_Turnpike_map.svg#file) I think we have success
It looked like you were trying to do something rather complicated with your plt.plot() statement. You have the list of longitudes and the list of lattitudes; that's all you need for plotting between the points in matplotlib, there's no need for enumerate or looping over lists. The following line should do the trick.
plt.plot(highway_lon, highway_lat, color='black', linewidth=1, marker='o', markersize=3, transform=ccrs.PlateCarree())
Here's the code with some unecessary bits removed.
import csv
import numpy as np
import matplotlib.pyplot as plt
import cartopy
import cartopy.crs as ccrs
# Open the file for highway metadata to read csv data
highway_metadata = open('milestone3data.csv', 'r')
metafile = csv.reader(highway_metadata, delimiter = ',')
# Create empty lists with highway data
highway_loc = []
highway_name = []
highway_lat = []
highway_lon = []
highway_dist = []
# Loop to transfer the csv file's data into the lists
for i in metafile:
highway_loc.append(i[0])
highway_name.append(i[1])
highway_lat.append(float(i[2]))
highway_lon.append(float(i[3]))
highway_dist.append(i[4])
def road_map():
fig = plt.figure(figsize=(10, 10))
proj = ccrs.Orthographic(central_longitude = -75,
central_latitude = 41)
ax = plt.axes(projection=proj)
ax.set_extent((-85,-70,36,45),crs=ccrs.PlateCarree())
# Set up the background
ax.add_feature(cartopy.feature.COASTLINE)
ax.add_feature(cartopy.feature.STATES)
plt.plot(highway_lon, highway_lat,
color='black', linewidth=1, marker='o', markersize=3,
transform=ccrs.PlateCarree())
plt.savefig('cartopytest7.png')
plt.show
road_map()
I have a problem witch updateing matplotlib chart. The problem is that i have many curve's on it, and after update the number of them may change. In example code I have 2 sets of data, 1st with 90 curves, and 2nd with 80, and i wish I could plot 1st set, and then 2nd, in the same matplotlib window.
import matplotlib.pyplot as plt
from matplotlib.transforms import Bbox
import numpy as np
from numpy.lib.polynomial import RankWarning
import pandas as pd
import sys
fig, ax = plt.subplots()
fig.subplots_adjust(right=0.78)
_x = []
_y = []
_y1 = []
_x1 = []
for x in range(90):
_x.append(np.linspace(0, 10*np.pi, 100))
_y.append(np.sin(_x[x])+x)
for x in range(80):
_x1.append(np.linspace(0, 10*np.pi, 150))
_y1.append(np.tan(_x1[x]+x))
def narysuj(__x, __y):
p = [] # p-pomiar
f = [] # f-czestotliwosc
for x in range(len(__x)):
p.append([])
f.append([])
ax.set_prop_cycle(color=plt.cm.gist_rainbow(np.linspace(0, 1, len(__x))))
for x in range(len(__x)):
for line in range(len(__x[x])):
#print(len(_y[x]), line)
p[x].append(__y[x][line])
f[x].append(__x[x][line])
ax.plot(f[x], p[x], label=f"Label {x}")
plt.show()
narysuj(_x, _y)
narysuj(_x1, _y1)
PS I know the way I'm drawing those charts is highly ineffective.
I found what was the problem. I had to add plt.ion() at the start of program and ax.clear() before drawing.
I'm trying to plot a set of points with a special feature,
first plot 2 points with a random coordinates x and y, in a range from 0 to 200,
but my problem is how can set this points as fixed or centers, take this center-points and from this points, plot one new point with random coordinates(as pairs of points A-a, B-b, etc), and define the distance that can't be higher than 30 meter or units of distance beetwen this points. To get the points like this
I add part of my code to make this
import matplotlib as mpl
from matplotlib.figure import Figure
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from itertools import product
from matplotlib.lines import Line2D
fig,ax=plt.subplots()
#AP POINTS
###################################################
points_xA=np.random.randint(0,200)
points_yA=np.random.randint(0,200)
points_xB=np.random.randint(0,200)
points_yB=np.random.randint(0,200)
center1=np.array([points_xA,points_yB])
center2=np.array([points_xB,points_yB])
ax.annotate("A",xy=(center1),fontsize=12,bbox={"boxstyle":"circle","color":"orange"})
ax.annotate("B",xy=(center2),fontsize=12,bbox={"boxstyle":"circle","color":"orange"})
#STA POINTS
######################################################
#points_xa=np.random.randint()
#points_ya=np.random.randint()
#points_xb=np.random.randint()
#points_yb=np.random.randint()
######################################################
#LABELS
plt.title('random points')
plt.xlabel('x(m)')
plt.ylabel('y(m)')
plt.xlim(0,210)
plt.ylim(0,210)
plt.grid(True)
plt.show()
i have develop a script that plot points as i wanted, but it have some issues:
1.- The menu or bar where the zoom functions, save image, etc. It disappeared and I can't zoom, which I think would be the most important thing.
2.- The table where is the coordinates of each point, for example, for AP_A it have his STA_A1 o more, depending how many STA's you want( for 3 STA's it would be STA_A1, STA_A2, STA_A3, etc)
but in the table apears as STA_A1, for any STA, in the next image it's more clear
I hope it will be useful to someone, on the other hand if someone can correct those errors in my code it would be great, I thank to this community where I have found some solutions on several occasions.
code:
import matplotlib as mpl
from matplotlib.figure import Figure
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from itertools import product
from matplotlib.lines import Line2D
##########################
#RADIOS
radius1=30
#radius2=30
#AP POINTS
###################################################
def setNodos(n,rango=300,n_clientes=6):
listaNodos = []
for i in range(n):
points_x=np.random.randint(0,rango)
points_y=np.random.randint(0,rango)
listaNodos.append((np.array([points_x,points_y]),n_clientes))
return listaNodos
listaNodos = setNodos(4,300,3)
abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
points_x = []
points_y = []
sta_cant = []
points_sta_x = []
points_sta_y = []
sta_names = []
for nodo,n in listaNodos:
points_x.append(nodo[0])
points_y.append(nodo[1])
sta_cant.append(n)
t_data=[]
########################################
fig = plt.figure(figsize = (15,10))
ax = plt.subplot2grid((3,2), (0, 0),colspan=2,rowspan=2)
l=0
sta_n=0
print(listaNodos)
for centerA,sta_n in listaNodos:
cxA,cyA = centerA
ax.annotate(abc[l],xy=(centerA),fontsize=12,bbox={"boxstyle":"circle","color":"orange"})
#RADIO CIRCULO ROJO
ct1A=np.linspace(0,2*np.pi)
circx11,circy12 = radius1*np.cos(ct1A)+cxA, radius1*np.sin(ct1A)+cyA
plt.plot(circx11, circy12, ls="-",color='red')
#RELLENO CIRCULO ROJO
ax= plt.gca()
t1= plt.Polygon([[i,j] for i, j in zip(circx11,circy12)], color='slategrey', alpha=0.2)
ax.add_patch(t1)
######################################################
#STA POINTS
######################################################
r_sta = np.random.randint(0,radius1,size=sta_n)
tita_sta = np.random.randint(0,359,size=sta_n)
x_sta = np.round(r_sta*np.cos(tita_sta)+cxA,0)
y_sta = np.round(r_sta*np.sin(tita_sta)+cyA,0)
print(x_sta,y_sta)
for x,y in zip(x_sta,y_sta):
#plt.scatter(x,y,c='b',zorder=1000)
x = np.min((300,np.max((0,int(x)))))
y = np.min((300,np.max((0,int(y)))))
ax.annotate(abc[l].lower(),xy=((x,y)),fontsize=10,color='black',
bbox={"boxstyle":"circle","color":"steelblue","alpha":0.5},
)
sta_names.append('STA_%s%i'%(abc[l],l+1))
points_sta_x.append(x)
points_sta_y.append(y)
l+=1
######################################################
#Tabla con coordenadas
plt.xlabel('x(m)')
plt.ylabel('y(m)')
plt.xlim(-10,310)
plt.ylim(-10,310)
ax.grid(True)
plt.title('random points')
t_data.append(points_x+points_sta_x)
t_data.append(points_y+points_sta_y)
print(t_data)
print(sta_n)
collLabels =[('AP_%s'%i) for i in abc[:len(points_x)]]
for name in sta_names:
collLabels.append(name)
print(collLabels)
ax1 = plt.subplot2grid((3,2), (2, 0),colspan=2,rowspan=1)
table=ax1.table(cellText = t_data,
colLabels=collLabels,
rowLabels=('coord_x','coord_y'),
bbox=[0,0.3,0.1+0.05*len(collLabels),0.6+0.01*len(collLabels)]
,cellLoc='center',fontsize=30)
plt.xticks([])
plt.yticks([])
plt.axis('OFF')
plt.tight_layout(rect=[0.01, 0.01, 1.0, 1.0])
#######################################################
#LABELS
ax.set_aspect('equal')
plt.savefig('./salida/escen_random.png')
plt.show()
I have been pulling my hair out for a while over this. I am trying to use mpldatacursor along with matplotlib to provide a tooltip functionality on scatter plots. Each point has some data associated with it which I would like to show when the point is clicked.
Here is a minimal (not) working example:
import numpy as np
import mpldatacursor
import string
import matplotlib
matplotlib.use('Qt5Agg')
from matplotlib import pyplot as mpl
nations = ['Russia', 'America', 'China', 'France']
data = list()
idx = list()
np.random.seed(42) #Seed for repeatability
# Random data
for (id, nation) in enumerate(nations):
for i in range(0,10):
data.append((id+1)*np.random.random((2,1)))
name = list(string.ascii_uppercase[20:])
np.random.shuffle(name)
idx.append(nation + '-' + ''.join(name))
mpl.figure()
data = np.squeeze(np.asarray(data))
m, n = 0, 9
# Plot by group
for (id,nation) in enumerate(nations):
mpl.scatter(data[m:n,0] , data[m:n,1] , label=nation)
m = n + 1
n += 10
formatter = lambda **kwargs: ', '.join(kwargs['point_label'])
mpl.legend()
mpldatacursor.datacursor(formatter=formatter, point_labels=idx)
mpl.show(block=True)
But when I do this, the tooltips don't match the legends. Further only labels starting with Russia and USA show up in the plot. What am I doing wrong?
Usually you would have your data in a table or, for the sake of the example, several lists. One would hence probably create a single scatter plot from the data columns and use a mapping of names to numbers to create the colors in the scatter.
Then one can use the matplotlib pick_event to get the data out of the respective list, given the index of the point on which the click happened.
This all does not require any external packages like datacursor.
import numpy as np; np.random.seed(42)
import string
from matplotlib import pyplot as plt
nations = ['Russia', 'America', 'China', 'France']
#Create lists data, nat, idx
nat = np.random.choice(nations, 50)
data = np.random.rand(50,2)
strings = ["".join(np.random.choice(list(string.ascii_uppercase), 7)) for _ in range(50)]
idx = ["{}-{}".format(n,w) for n,w in zip(nat,strings)]
labels, i = np.unique(nat, return_inverse=True)
fig, ax = plt.subplots()
scatter = ax.scatter(data[:,0], data[:,1], c=i, cmap="RdYlGn", picker=5)
rect = lambda c: plt.Rectangle((0,0),1,1, color=scatter.cmap(scatter.norm(c)))
handles = [rect(c) for c in np.unique(i)]
plt.legend(handles, labels)
#Create annotation
annot = ax.annotate("", xy=(0,0), xytext=(-20,20),textcoords="offset points",
bbox=dict(boxstyle="round", fc="w"),
arrowprops=dict(arrowstyle="->"))
annot.set_visible(False)
#Create event handler
def onpick(evt):
if evt.artist == scatter:
ind = evt.ind[0]
annot.xy = (data[ind])
annot.set_text(idx[ind])
annot.set_visible(True)
if evt.mouseevent.button == 3:
annot.set_visible(False)
fig.canvas.draw_idle()
fig.canvas.mpl_connect("pick_event", onpick)
plt.show()
The issue was that each call to scatter by matplotlib was creating a new artist object. The workaround is based on the doc-string in the source code.
point_labels : sequence or dict, optional
Labels for "subitems" of an artist, passed to the formatter
function as the point_label kwarg. May be either a single
sequence (used for all artists) or a dict of artist:sequence pairs.
It does involve the import of a protected matplotlib module/member. This seems to work as I want:
import numpy as np
import mpldatacursor
import string
import matplotlib
from matplotlib import _pylab_helpers as pylab_helpers
matplotlib.use('Qt5Agg')
from matplotlib import pyplot as mpl
nations = ['Russia', 'America', 'China', 'France']
data = list()
idx = list()
np.random.seed(42)
for (index, nation) in enumerate(nations):
for i in range(0,10):
data.append((index + 1) * np.random.random((2, 1)))
name = list(string.ascii_uppercase[20:])
np.random.shuffle(name)
idx.append(nation + '-' + ''.join(name))
data = np.squeeze(np.asarray(data))
m, n = 0, 9
artist_labels = list()
mpl.figure()
for (index, nation) in enumerate(nations):
mpl.scatter(data[m:n,0] , data[m:n,1] ,label=nation)
artist_labels.append(idx[m:n])
m = n + 1
n += 10
def plotted_artists(ax):
all_artists = (ax.lines + ax.patches + ax.collections
+ ax.images + ax.containers)
return all_artists
def formatter (**kwargs):
return kwargs['point_label'].pop()
managers = pylab_helpers.Gcf.get_all_fig_managers()
figs = [manager.canvas.figure for manager in managers]
axes = [ax for fig in figs for ax in fig.axes]
artists = [artist for ax in axes for artist in plotted_artists(ax)]
my_dict = dict(zip(artists, artist_labels))
mpldatacursor.datacursor(formatter=formatter, point_labels=my_dict)
mpl.legend()
mpl.show(block=True)
Assuming you simply want names, this seems to work correctly if you change the mpldatacursor.datacursor call to use '{label}' as in the first example on the mpldatacursor website,
mpldatacursor.datacursor(formatter='{label}'.format)
I think the problem is with kwargs and the lambda function. If you want further data in your tooltip, it may be best to add this to the label on plt.scatter, using a separate call for each point, e.g.
import numpy as np
import mpldatacursor
import string
import matplotlib
matplotlib.use('Qt5Agg')
from matplotlib import pyplot as plt
nations = ['Russia', 'America', 'China', 'France']
cDict = {'Russia':'r', 'America':'b', 'China':'g', 'France':'c'}
np.random.seed(42) #Seed for repeatability
# Random data
for (id, nation) in enumerate(nations):
for i in range(0,10):
x = (id+1)*np.random.random((2,1))
name = list(string.ascii_uppercase[20:])
np.random.shuffle(name)
plt.scatter(x[0], x[1], c=cDict[nation], label=nation + '-' + ''.join(name))
mpldatacursor.datacursor(formatter='{label}'.format)
plt.show(block=True)
I'm trying to plot filled polygons of countries on the world map with matplotlib in python.
I've got a shapefile with country boundary coordinates of every country. Now, I want to convert these coordinates (for each country) into a polygon with matplotlib. Without using Basemap. Unfortunately, the parts are crossing or overlapping. Is there a workarund, maybe using the distance from point to point.. or reordering them ?
Ha!
I found out, how.. I completely neglected, the sf.shapes[i].parts information! Then it comes down to:
# -- import --
import shapefile
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from matplotlib.patches import Polygon
from matplotlib.collections import PatchCollection
# -- input --
sf = shapefile.Reader("./shapefiles/world_countries_boundary_file_world_2002")
recs = sf.records()
shapes = sf.shapes()
Nshp = len(shapes)
cns = []
for nshp in xrange(Nshp):
cns.append(recs[nshp][1])
cns = array(cns)
cm = get_cmap('Dark2')
cccol = cm(1.*arange(Nshp)/Nshp)
# -- plot --
fig = plt.figure()
ax = fig.add_subplot(111)
for nshp in xrange(Nshp):
ptchs = []
pts = array(shapes[nshp].points)
prt = shapes[nshp].parts
par = list(prt) + [pts.shape[0]]
for pij in xrange(len(prt)):
ptchs.append(Polygon(pts[par[pij]:par[pij+1]]))
ax.add_collection(PatchCollection(ptchs,facecolor=cccol[nshp,:],edgecolor='k', linewidths=.1))
ax.set_xlim(-180,+180)
ax.set_ylim(-90,90)
fig.savefig('test.png')
Then it will look like this:
Here is another piece of code I used to plot polygon shapefiles. It uses GDAL/OGR to read shapefile and plots correctly donut shape polygons:
from osgeo import ogr
import numpy as np
import matplotlib.path as mpath
import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
# Extract first layer of features from shapefile using OGR
ds = ogr.Open('world_countries_boundary_file_world_2002.shp')
nlay = ds.GetLayerCount()
lyr = ds.GetLayer(0)
# Get extent and calculate buffer size
ext = lyr.GetExtent()
xoff = (ext[1]-ext[0])/50
yoff = (ext[3]-ext[2])/50
# Prepare figure
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_xlim(ext[0]-xoff,ext[1]+xoff)
ax.set_ylim(ext[2]-yoff,ext[3]+yoff)
paths = []
lyr.ResetReading()
# Read all features in layer and store as paths
for feat in lyr:
geom = feat.geometry()
codes = []
all_x = []
all_y = []
for i in range(geom.GetGeometryCount()):
# Read ring geometry and create path
r = geom.GetGeometryRef(i)
x = [r.GetX(j) for j in range(r.GetPointCount())]
y = [r.GetY(j) for j in range(r.GetPointCount())]
# skip boundary between individual rings
codes += [mpath.Path.MOVETO] + \
(len(x)-1)*[mpath.Path.LINETO]
all_x += x
all_y += y
path = mpath.Path(np.column_stack((all_x,all_y)), codes)
paths.append(path)
# Add paths as patches to axes
for path in paths:
patch = mpatches.PathPatch(path, \
facecolor='blue', edgecolor='black')
ax.add_patch(patch)
ax.set_aspect(1.0)
plt.show()
from fiona import collection
import matplotlib.pyplot as plt
from descartes import PolygonPatch
from matplotlib.collections import PatchCollection
from itertools import imap
from matplotlib.cm import get_cmap
cm = get_cmap('Dark2')
figure, axes = plt.subplots(1)
source_path = "./shapefiles/world_countries_boundary_file_world_2002"
with collection(source_path, 'r') as source:
patches = imap(PolygonPatch, (record['geometry'] for record in source)
axes.add_collection( PatchCollection ( patches, cmap=cm, linewidths=0.1 ) )
axes.set_xlim(-180,+180)
axes.set_ylim(-90,90)
plt.show()
Note this assumes polygons, MultiPolygons can be handles in a similar manner with
map(PolygonPatch, MultiPolygon(record['geometry']))
Regarding to #hannesk's answer, you should add the following imports: from numpy import array and import matplotlib and replace the line cm = get_cmap('Dark2') by cm = matplotlib.cm.get_cmap('Dark2')
(I'm not so famous to add a comment to the noticed post.)