Ich zeichne eine Karte mit Grundkarte von Matplotlib. Die Daten sind auf der ganzen Welt verteilt, aber ich möchte nur alle Daten auf dem Kontinent behalten und diese auf den Ozean fallen lassen. Gibt es eine Möglichkeit, die Daten zu filtern, oder gibt es eine Möglichkeit, den Ozean erneut zu zeichnen, um die Daten zu erfassen?Plot nur auf Kontinent in Matplotlib
Antwort
Es gibt Verfahren, bei matplotlib.basemap: is_land(xpt, ypt)
Es gibt True
wenn die gegebenen x, y Punkt (in Projektionskoordinaten) über Land ist, False
anderweitig. Die Definition von Land basiert auf den GSHHS-Küstenlinienpolygonen, die der Klasseninstanz zugeordnet sind. Punkte über Seen innerhalb von Landregionen werden nicht als Landpunkte gezählt.
Weitere Informationen finden Sie unter here.
is_land()
werden alle Polygone durchlaufen, um zu prüfen, ob es sich um Land handelt oder nicht. Für große Datenmengen ist es sehr langsam. Sie können points_inside_poly()
von Matplotlib verwenden, um ein Array von Punkten schnell zu überprüfen. Hier ist der Code. Es überprüft nicht lakepolygons
, wenn Sie Punkte in Seen entfernen möchten, können Sie Ihr Selbst hinzufügen.
Es dauerte 2,7 Sekunden, um 100000 Punkte auf meinem PC zu überprüfen. Wenn Sie mehr Geschwindigkeit wünschen, können Sie die Polygone in eine Bitmap konvertieren, aber es ist ein wenig schwierig, dies zu tun. Bitte sagen Sie mir, ob der folgende Code für Ihr Dataset nicht schnell genug ist.
from mpl_toolkits.basemap import Basemap
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.nxutils as nx
def points_in_polys(points, polys):
result = []
for poly in polys:
mask = nx.points_inside_poly(points, poly)
result.extend(points[mask])
points = points[~mask]
return np.array(result)
points = np.random.randint(0, 90, size=(100000, 2))
m = Basemap(projection='moll',lon_0=0,resolution='c')
m.drawcoastlines()
m.fillcontinents(color='coral',lake_color='aqua')
x, y = m(points[:,0], points[:,1])
loc = np.c_[x, y]
polys = [p.boundary for p in m.landpolygons]
land_loc = points_in_polys(loc, polys)
m.plot(land_loc[:, 0], land_loc[:, 1],'ro')
plt.show()
Ich denke 'points_inside_poly' (und wenn ich mich an die ganzen 'nxutils' erinnere) wird in MPL 1 abgeschrieben.2, aber es funktioniert auch mit der neuen Methode (kann mich nicht erinnern, was die neue Methode im Moment ist, aber die Abschreibung Warnung wird es sagen) – bmu
https://matplotlib.org/1.2.1/api/path_api.html # matplotlib.path.Path.contains_points – Baz
Die Antwort des Hyry wird auf neue Versionen von matplotlib nicht (nxutils ist veraltet). Ich habe eine neue Version gemacht, die funktionieren:
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
from matplotlib.path import Path
import numpy as np
map = Basemap(projection='cyl', resolution='c')
lons = [0., 0., 16., 76.]
lats = [0., 41., 19., 51.]
x, y = map(lons, lats)
locations = np.c_[x, y]
polygons = [Path(p.boundary) for p in map.landpolygons]
result = np.zeros(len(locations), dtype=bool)
for polygon in polygons:
result += np.array(polygon.contains_points(locations))
print result
Der einfachste Weg basemap die maskoceans zu verwenden ist.
Nach meshgrid und Interpolation:
from scipy.interpolate import griddata as gd
from mpl_toolkits.basemap import Basemap, cm, maskoceans
xi, yi = np.meshgrid(xi, yi)
zi = gd((mlon, mlat),
scores,
(xi, yi),
method=grid_interpolation_method)
#mask points on ocean
data = maskoceans(xi, yi, zi)
con = m.contourf(xi, yi, data, cmap=cm.GMT_red2green)
#note instead of zi we have data now.
ich this question beantworten, als mir gesagt wurde, dass es besser wäre, meine Antwort hier zu posten. Im Wesentlichen extrahiert meine Lösung die Polygone, die zum Zeichnen der Küstenlinie der Instanz verwendet werden, und kombiniert diese Polygone mit dem Umriss der Karte, um eine matplotlib.PathPatch
zu erzeugen, die die Meeresgebiete der Karte überlagert.
Dies ist besonders nützlich, wenn die Daten grob sind und eine Interpolation der Daten nicht erwünscht ist. In diesem Fall erzeugt die Verwendung von maskoceans
einen sehr körnigen Umriss der Küstenlinien, der nicht sehr gut aussieht.
Hier ist das gleiche Beispiel, das ich als Antwort auf die andere Frage gestellt:
from matplotlib import pyplot as plt
from mpl_toolkits import basemap as bm
from matplotlib import colors
import numpy as np
import numpy.ma as ma
from matplotlib.patches import Path, PathPatch
fig, ax = plt.subplots()
lon_0 = 319
lat_0 = 72
##some fake data
lons = np.linspace(lon_0-60,lon_0+60,10)
lats = np.linspace(lat_0-15,lat_0+15,5)
lon, lat = np.meshgrid(lons,lats)
TOPO = np.sin(np.pi*lon/180)*np.exp(lat/90)
m = bm.Basemap(resolution='i',projection='laea', width=1500000, height=2900000, lat_ts=60, lat_0=lat_0, lon_0=lon_0, ax = ax)
m.drawcoastlines(linewidth=0.5)
x,y = m(lon,lat)
pcol = ax.pcolormesh(x,y,TOPO)
##getting the limits of the map:
x0,x1 = ax.get_xlim()
y0,y1 = ax.get_ylim()
map_edges = np.array([[x0,y0],[x1,y0],[x1,y1],[x0,y1]])
##getting all polygons used to draw the coastlines of the map
polys = [p.boundary for p in m.landpolygons]
##combining with map edges
polys = [map_edges]+polys[:]
##creating a PathPatch
codes = [
[Path.MOVETO] + [Path.LINETO for p in p[1:]]
for p in polys
]
polys_lin = [v for p in polys for v in p]
codes_lin = [c for cs in codes for c in cs]
path = Path(polys_lin, codes_lin)
patch = PathPatch(path,facecolor='white', lw=0)
##masking the data:
ax.add_patch(patch)
plt.show()
Daraus ergibt sich die folgende Handlung:
Hoffe, das ist hilfreich für jemand :)
Danke das ist, was ich gesucht habe. Aber wenn ich 'is_land' benutze, stoße ich auf ein Problem. Es ist [hier] (http://stackoverflow.com/q/13800056/1819734). – ZYX