边界内的等高线图数据(纬度、经度、值)并导出 GeoJSON
Contour plot data (lat,lon,value) within boundaries and export GeoJSON
我正在尝试根据来自 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 的输出,为了方便起见,至少需要使用 shapely
module (and here geopandas
。 =21=]
import numpy as np
import matplotlib.pyplot as plt
from geopandas import GeoDataFrame
from matplotlib.mlab import griddata
from shapely.geometry import Polygon, MultiPolygon
def collec_to_gdf(collec_poly):
"""Transform a `matplotlib.contour.QuadContourSet` to a GeoDataFrame"""
polygons, colors = [], []
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)
colors.append(polygon.get_facecolor().tolist()[0])
elif len(mpoly) == 1:
polygons.append(mpoly[0])
colors.append(polygon.get_facecolor().tolist()[0])
return GeoDataFrame(
geometry=polygons,
data={'RGBA': colors},
crs={'init': 'epsg:4326'})
data = np.genfromtxt('temp.csv', delimiter=',')
x = data[..., 1]
y = data[..., 2]
z = data[..., 3]
xi = np.linspace(x.min(), x.max(), 200)
yi = np.linspace(y.min(), y.max(), 200)
zi = griddata(x, y, z, xi, yi, interp='linear') # You could also take a look to scipy.interpolate.griddata
nb_class = 15 # 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()
# Output your collection of features as a GeoJSON:
# '{"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Polygon", "coordinates": [[[51.563214073747474,
# (...)
编辑:
您可以获取 matplotplib 使用的颜色值(作为 0-1 范围内的 4 个值的数组,表示 RGBA 值),方法是使用 get_facecolor()
方法在集合的每个项目上获取它们(然后使用它们填充GeoDataFrame 的一(或 4)列:
colors = [p.get_facecolor().tolist()[0] for p in collec_poly.collections]
gdf['RGBA'] = colors
一旦你有了 GeoDataFrame,你就可以很容易地让它与你的边界相交。使用这些边界来制作一个具有形状的多边形并计算与结果的交集:
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()
我正在尝试根据来自 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 的输出,为了方便起见,至少需要使用 shapely
module (and here geopandas
。 =21=]
import numpy as np
import matplotlib.pyplot as plt
from geopandas import GeoDataFrame
from matplotlib.mlab import griddata
from shapely.geometry import Polygon, MultiPolygon
def collec_to_gdf(collec_poly):
"""Transform a `matplotlib.contour.QuadContourSet` to a GeoDataFrame"""
polygons, colors = [], []
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)
colors.append(polygon.get_facecolor().tolist()[0])
elif len(mpoly) == 1:
polygons.append(mpoly[0])
colors.append(polygon.get_facecolor().tolist()[0])
return GeoDataFrame(
geometry=polygons,
data={'RGBA': colors},
crs={'init': 'epsg:4326'})
data = np.genfromtxt('temp.csv', delimiter=',')
x = data[..., 1]
y = data[..., 2]
z = data[..., 3]
xi = np.linspace(x.min(), x.max(), 200)
yi = np.linspace(y.min(), y.max(), 200)
zi = griddata(x, y, z, xi, yi, interp='linear') # You could also take a look to scipy.interpolate.griddata
nb_class = 15 # 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()
# Output your collection of features as a GeoJSON:
# '{"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Polygon", "coordinates": [[[51.563214073747474,
# (...)
编辑:
您可以获取 matplotplib 使用的颜色值(作为 0-1 范围内的 4 个值的数组,表示 RGBA 值),方法是使用 get_facecolor()
方法在集合的每个项目上获取它们(然后使用它们填充GeoDataFrame 的一(或 4)列:
colors = [p.get_facecolor().tolist()[0] for p in collec_poly.collections]
gdf['RGBA'] = colors
一旦你有了 GeoDataFrame,你就可以很容易地让它与你的边界相交。使用这些边界来制作一个具有形状的多边形并计算与结果的交集:
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()