代码之家  ›  专栏  ›  技术社区  ›  Arn

如何防止散点图超出shapefile映射?[复制]

  •  0
  • Arn  · 技术社区  · 8 年前

    我正在使用matplotlib中的basemap绘制地图。数据分布在世界各地,但我只想保留大陆上的所有数据,并把它们放到海洋上。有没有一种方法可以过滤数据,还是有办法再次绘制海洋来覆盖数据?

    0 回复  |  直到 13 年前
        1
  •  6
  •   Timothy    13 年前

    有方法在里面matplotlib.basemap: is_land(xpt, ypt)

    True 如果给定的x,y点(在投影坐标系中)在陆地上, False 否则。土地的定义基于与类实例关联的GSHHS海岸线多边形。陆地区域内湖泊上方的点不算作陆地点。

    有关详细信息,请参阅 here .

        2
  •  6
  •   HYRY    13 年前

    is_land() points_inside_poly() lakepolygons ,如果你想删除湖泊中的点,你可以添加你自己。

    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()
    
        3
  •  4
  •   Roger Veciana    11 年前

    HYRY的答案在matplotlib的新版本上不起作用(nxutils被弃用)。我做了一个新的版本:

    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
    
        4
  •  4
  •   Thomas Kühn    8 年前

    我在回答 this question ,当我被告知最好把我的答案张贴在这里。基本上,我的解决方案提取了用来绘制海岸线的多边形 Basemap 并将这些多边形与实例相结合以生成多边形的轮廓 matplotlib.PathPatch 覆盖了地图上的海洋区域。

    如果数据是粗糙的并且不需要数据的插值,这一点尤其有用。在这种情况下使用 maskoceans

    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()
    

    这将生成以下绘图:

    enter image description here

    希望这对某人有帮助:)

        5
  •  3
  •   Ash    8 年前

    maskoceans .

    使用轮廓: 网格网格和插值之后:

    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.
    

    更新(比在_land或in_polygon解决方案中更快):

    如果对于每个lat,lon,您没有任何数据,而您只想将点分散在陆地上:

    x, y = m(lons, lats)
    samples = len(lons)
    ocean = maskoceans(lons, lats, datain=np.arange(samples),
                       resolution='i')
    ocean_samples = np.ma.count_masked(ocean)
    print('{0} of {1} points in ocean'.format(ocean_samples, samples))
    m.scatter(x[~ocean.mask], y[~ocean.mask], marker='.', color=colors[~ocean.mask], s=1)
    m.drawcountries()
    m.drawcoastlines(linewidth=0.7)
    plt.savefig('a.png')