Python 边界内的等高线图数据(纬度、经度、值)并导出GeoJSON

Python 边界内的等高线图数据(纬度、经度、值)并导出GeoJSON,python,csv,interpolation,geojson,contour,Python,Csv,Interpolation,Geojson,Contour,我正在尝试在边界内插值数据,并根据来自csv文件的纬度、经度和值数据绘制等高线(多边形) 结果我希望打印为geojson 我被困在csv的基本等高线图上。我真的很感谢你的帮助 这就是我在这一刻得到的,但无法让它发挥作用 import numpy as np import matplotlib.pyplot as plt data = np.genfromtxt('temp.csv', delimiter=',') x = data[:1] y = data[:2] [x,y] = mesh

我正在尝试在边界内插值数据,并根据来自csv文件的纬度、经度和值数据绘制等高线(多边形)

结果我希望打印为geojson

我被困在csv的基本等高线图上。我真的很感谢你的帮助

这就是我在这一刻得到的,但无法让它发挥作用

import numpy as np
import matplotlib.pyplot as plt


data = np.genfromtxt('temp.csv', delimiter=',')

x = data[:1]
y = data[:2]
[x,y] = meshgrid(x,y);
z = data[:3];

plt.contour(x,y,z)
plt.show()
CSV看起来像这样

2015-10-28T09:25:12.800Z,51.56325,17.529043333,4.6484375,19.8046875
2015-10-28T09:25:12.900Z,51.56325,17.529041667,4.4921875,19.6875
2015-10-28T09:25:13.000Z,51.563248333,17.529041667,4.453125,19.9609375
2015-10-28T09:25:13.200Z,51.563245,17.529041667,4.140625,19.765625
2015-10-28T09:25:13.300Z,51.563243333,17.529041667,4.609375,19.6484375
2015-10-28T09:25:13.500Z,51.563241667,17.529041667,4.609375,19.53125
2015-10-28T09:25:13.600Z,51.56324,17.529041667,4.4921875,19.375
2015-10-28T09:25:13.700Z,51.563238333,17.529041667,4.4140625,19.765625
2015-10-28T09:25:13.800Z,51.563236667,17.529041667,4.453125,20.234375
2015-10-28T09:25:13.900Z,51.563235,17.529041667,4.3359375,19.84375
2015-10-28T09:25:14.000Z,51.563233333,17.529041667,4.53125,19.453125
2015-10-28T09:25:14.100Z,51.563231667,17.529041667,4.53125,19.8046875
2015-10-28T09:25:14.200Z,51.563228333,17.529041667,4.1796875,19.4921875
2015-10-28T09:25:14.300Z,51.563226667,17.529041667,4.2578125,19.453125
2015-10-28T09:25:14.400Z,51.563225,17.529041667,4.4921875,19.4921875
2015-10-28T09:25:14.500Z,51.563223333,17.529041667,4.375,19.453125
2015-10-28T09:25:14.600Z,51.563221667,17.529041667,4.609375,18.90625
2015-10-28T09:25:14.700Z,51.563218333,17.529041667,4.53125,19.6875
2015-10-28T09:25:14.900Z,51.563215,17.529041667,4.140625,18.75
2015-10-28T09:25:15.000Z,51.563213333,17.529041667,4.453125,18.828125
第1栏-纬度 第2列-经度 第3列-值


对于等高线,我还需要限制-例如(4.1,4.3,4.6)

我猜您的代码中有一些错误(根据您的数据,您不应该执行
x=data[:1]
,但更多
x=data[…,1]

对于您的数据类型,我将遵循的基本步骤是插值
z
值并获取作为geojson的输出,这至少需要模块(这里是为了方便而使用的)

编辑: 通过使用
get\u facecolor()
方法在集合的每个项目上获取matplotplib使用的颜色值(作为范围为0-1的4个值的数组,表示RGBA值),然后使用它们填充GeoDataFrame的一(或4)列:

colors = [p.get_facecolor().tolist()[0] for p in collec_poly.collections]
gdf['RGBA'] = colors
一旦有了GeoDataFrame,就可以很容易地使其与边界相交。使用这些边界创建一个具有shapely的多边形,并使用结果计算相交:

mask = Polygon([(51,17), (51,18), (52,18), (52,17), (51,17)])
gdf.geometry = gdf.geometry.intersection(mask)
或者将geojson作为GeoDataFrame读取:

from shapely.ops import unary_union, polygonize
boundary = GeoDataFrame.from_file('your_geojson')
# Assuming you have a boundary as linestring, transform it to a Polygon:
mask_geom = unary_union([i for i in polygonize(boundary.geometry)])
# Then compute the intersection:
gdf.geometry = gdf.geometry.intersection(mask_geom)

我猜您的代码中有一些错误(根据您的数据,您不应该执行
x=data[:1]
,但更多的是
x=data[…,1]

对于您的数据类型,我将遵循的基本步骤是插值
z
值并获取作为geojson的输出,这至少需要模块(这里是为了方便而使用的)

编辑: 通过使用
get\u facecolor()
方法在集合的每个项目上获取matplotplib使用的颜色值(作为范围为0-1的4个值的数组,表示RGBA值),然后使用它们填充GeoDataFrame的一(或4)列:

colors = [p.get_facecolor().tolist()[0] for p in collec_poly.collections]
gdf['RGBA'] = colors
一旦有了GeoDataFrame,就可以很容易地使其与边界相交。使用这些边界创建一个具有shapely的多边形,并使用结果计算相交:

mask = Polygon([(51,17), (51,18), (52,18), (52,17), (51,17)])
gdf.geometry = gdf.geometry.intersection(mask)
或者将geojson作为GeoDataFrame读取:

from shapely.ops import unary_union, polygonize
boundary = GeoDataFrame.from_file('your_geojson')
# Assuming you have a boundary as linestring, transform it to a Polygon:
mask_geom = unary_union([i for i in polygonize(boundary.geometry)])
# Then compute the intersection:
gdf.geometry = gdf.geometry.intersection(mask_geom)

几乎我得到了我所期望的。基于mgc的答案。我按照您的建议将griddata更改为scipy.interpolate.griddata,并将插值方法更改为“最近”。现在它的工作方式符合我的要求

我需要做的最后一件事是将此插值也从geoJson限制到多边形(边界)

另一个问题是将颜色作为属性导出到geojson多边形

import numpy as np
import matplotlib.pyplot as plt
#from matplotlib.mlab import griddata
from scipy.interpolate import griddata

from geopandas import GeoDataFrame
from shapely.geometry import Polygon, MultiPolygon

def collec_to_gdf(collec_poly):
    """Transform a `matplotlib.contour.QuadContourSet` to a GeoDataFrame"""
    polygons = []
    for i, polygon in enumerate(collec_poly.collections):
        mpoly = []
        for path in polygon.get_paths():
            try:
                path.should_simplify = False
                poly = path.to_polygons()
                # Each polygon should contain an exterior ring + maybe hole(s):
                exterior, holes = [], []
                if len(poly) > 0 and len(poly[0]) > 3:
                    # The first of the list is the exterior ring :
                    exterior = poly[0]
                    # Other(s) are hole(s):
                    if len(poly) > 1:
                        holes = [h for h in poly[1:] if len(h) > 3]
                mpoly.append(Polygon(exterior, holes))
            except:
                print('Warning: Geometry error when making polygon #{}'
                      .format(i))
        if len(mpoly) > 1:
            mpoly = MultiPolygon(mpoly)
            polygons.append(mpoly)
        elif len(mpoly) == 1:
            polygons.append(mpoly[0])
    return GeoDataFrame(geometry=polygons, crs={'init': 'epsg:4326'})

data = np.genfromtxt('temp2.csv', delimiter=',')
x = data[..., 1]
y = data[..., 2]
z = data[..., 4]
xi = np.linspace(x.min(), x.max(), num=100)
yi = np.linspace(y.min(), y.max(), num=100)

#zi = griddata(x, y, z, xi, yi, interp='nn') # You could also take a look to scipy.interpolate.griddata
zi = griddata((x, y), z, (xi[None,:], yi[:,None]), method='nearest')

nb_class = [5,10,15,20,25,30,35,40,45,50] # Set the number of class for contour creation
# The class can also be defined by their limits like [0, 122, 333]
collec_poly = plt.contourf(
    xi, yi, zi, nb_class, vmax=abs(zi).max(), vmin=-abs(zi).max())

gdf = collec_to_gdf(collec_poly)
#gdf.to_json()
print gdf.to_json()

plt.plot(x,y)

plt.show()

几乎我得到了我所期望的。基于mgc的答案。我按照您的建议将griddata更改为scipy.interpolate.griddata,并将插值方法更改为“最近”。现在它的工作方式符合我的要求

我需要做的最后一件事是将此插值也从geoJson限制到多边形(边界)

另一个问题是将颜色作为属性导出到geojson多边形

import numpy as np
import matplotlib.pyplot as plt
#from matplotlib.mlab import griddata
from scipy.interpolate import griddata

from geopandas import GeoDataFrame
from shapely.geometry import Polygon, MultiPolygon

def collec_to_gdf(collec_poly):
    """Transform a `matplotlib.contour.QuadContourSet` to a GeoDataFrame"""
    polygons = []
    for i, polygon in enumerate(collec_poly.collections):
        mpoly = []
        for path in polygon.get_paths():
            try:
                path.should_simplify = False
                poly = path.to_polygons()
                # Each polygon should contain an exterior ring + maybe hole(s):
                exterior, holes = [], []
                if len(poly) > 0 and len(poly[0]) > 3:
                    # The first of the list is the exterior ring :
                    exterior = poly[0]
                    # Other(s) are hole(s):
                    if len(poly) > 1:
                        holes = [h for h in poly[1:] if len(h) > 3]
                mpoly.append(Polygon(exterior, holes))
            except:
                print('Warning: Geometry error when making polygon #{}'
                      .format(i))
        if len(mpoly) > 1:
            mpoly = MultiPolygon(mpoly)
            polygons.append(mpoly)
        elif len(mpoly) == 1:
            polygons.append(mpoly[0])
    return GeoDataFrame(geometry=polygons, crs={'init': 'epsg:4326'})

data = np.genfromtxt('temp2.csv', delimiter=',')
x = data[..., 1]
y = data[..., 2]
z = data[..., 4]
xi = np.linspace(x.min(), x.max(), num=100)
yi = np.linspace(y.min(), y.max(), num=100)

#zi = griddata(x, y, z, xi, yi, interp='nn') # You could also take a look to scipy.interpolate.griddata
zi = griddata((x, y), z, (xi[None,:], yi[:,None]), method='nearest')

nb_class = [5,10,15,20,25,30,35,40,45,50] # Set the number of class for contour creation
# The class can also be defined by their limits like [0, 122, 333]
collec_poly = plt.contourf(
    xi, yi, zi, nb_class, vmax=abs(zi).max(), vmin=-abs(zi).max())

gdf = collec_to_gdf(collec_poly)
#gdf.to_json()
print gdf.to_json()

plt.plot(x,y)

plt.show()

我想在您的代码和使用geojson作为输出之间有几步。您在运行代码时是否遇到一些错误消息?我想在您的代码和使用geojson作为输出之间有几步。您在运行代码时是否遇到一些错误消息?谢谢,这将对我有很大帮助。我正在尝试绘制结果st但如果我使用所有关于40k点的数据,我会出错。griddata中出错(运行时错误:初始化中:三角剖分无效)。可能我需要先对这些数据排序?但是如何排序?我将边界作为多边形(有时甚至是带孔的多边形)在geojson文件中。geometry.intersection给了我非常奇怪的结果。只显示内部最小的多边形。关于RGBA颜色,我有一个错误:gdf['RGBA']处的“ValueError:值的长度与索引的长度不匹配”=颜色很抱歉。我没有在边界多边形上使用此一元联合函数。现在它看起来可以工作了。如果您能检查为什么此颜色对我不起作用,那就太好了。如果您的边界文件有多个功能,您应该在
gdf.geometry.cross之前尝试
mask\u geom=一元联合(您的边界\u gdf.geometry)
(mask_geom)
。关于颜色,我想这是因为matplotlib集合中的某些多边形没有作为形状几何体获取(无效的)因此它可以解释长度的不匹配。更安全的方法是在
collec_to_gdf
函数中为创建的每个多边形提取它们。@user3476099我编辑了
collec_to_gdf
函数,因此它应该输出一个
地理数据框
,其中包含一列RGBA值。谢谢,这将对我有很大帮助。我尝试首先绘制结果,但如果我使用所有关于40k点的数据,则会出现错误。griddata中存在错误(运行时错误:初始化中:三角剖分无效)。可能我需要首先对这些数据进行排序?但是如何排序?我将边界作为多边形(有时甚至是带孔的多边形)在geojson文件中。geometry.intersection给了我非常奇怪的结果。只显示内部最小的多边形。关于RGBA颜色,我有一个错误:gdf['RGBA']处的“ValueError:值的长度与索引的长度不匹配”=颜色很抱歉。我没有在边界多边形上使用此一元联合函数。现在它看起来可以工作了。如果您能检查为什么此颜色对我不起作用,那就太好了。如果您的边界文件有多个功能,您应该在
gdf.geometry.cross之前尝试
mask\u geom=一元联合(您的边界\u gdf.geometry)
(mask_geom)
。关于颜色,我想这是因为matplotlib集合中的某些多边形没有作为形状几何体获取(无效的)因此它可以解释长度不匹配的原因。更安全的方法是在
collec_to_gdf
函数中为创建的每个多边形提取它们。@user3476099我编辑了
collec_t