在指定的JSON边界内绘制hexbin截止值

ruarlubt  于 2023-04-13  发布在  其他
关注(0)|答案(1)|浏览(208)

我正在绘制一个单独的hexbin图和json边界文件。hexbin网格与边界文件重叠。我只想显示非洲大陆。我的目标是在非洲大陆内切断或子集hexbin网格**。因此,边界文件外部不应显示网格正方形。是否有方法使用Plotly实现这一点?

import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objs as go
import plotly.figure_factory as ff
import geopandas as gpd
import json

data = pd.DataFrame({
    'LAT': [1,5,6,7,5,6,7,5,6,7,5,6,7,12,-40,50],
    'LON': [10,10,11,12,10,11,12,10,11,12,10,11,12,-20,40,50],
    })

gdf_poly = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
gdf_poly = gdf_poly.drop('name', axis = 1)

Afr_gdf_area = gdf_poly[gdf_poly['continent'] == 'Africa'].reset_index(drop = True)

fig = ff.create_hexbin_mapbox(data_frame=data,
                       lat="LAT", 
                       lon="LON",
                       nx_hexagon=25,
                       opacity=0.4,
                       labels={"color": "Point Count"},
                       mapbox_style='carto-positron',
                       zoom = 1
                       )

fig.update_layout(mapbox={
        "layers": [
            {"source": json.loads(Afr_gdf_area.geometry.to_json()),
                "below": "traces",
                "type": "fill",
                "color": "orange",
                "opacity" : 0.1,
                "line": {"width": 1}
            },
        ],
    })   

fig.show()

预期输出是切断或剪辑广场以外的非洲满意度,这是在橙子。

8aqjt8rx

8aqjt8rx1#

如果你看一下fig.data[0]的内部,它是一个Choroplethmapbox,有几个字段,包括customdatageojson。geojson包含绘制hexbin所需的所有信息,包括每个六边形的coordinates和唯一的id。customdata是一个形状为[n_hexbins x 3]的数组,其中数组的每个元素都包括id和plotly用于确定每个hexbin颜色的数值。

'customdata': array([[0.0, '-0.3490658516205964,-0.7648749219440846', 0],
                         [0.0, '-0.3490658516205964,-0.6802309514438665', 0],
                         [0.0, '-0.3490658516205964,-0.5955869809436484', 0],
                         ...,
                         [0.0, '0.8482300176421051,0.8010385323099501', 0],
                         [0.0, '0.8482300176421051,0.8856825028101681', 0],
                         [0.0, '0.8482300176421051,0.9703264733103861', 0]], dtype=object),
    'geojson': {'features': [{'geometry': {'coordinates': [[[-20.00000007,
                                                           -41.31174966478728],
                                                           [-18.6000000672,
                                                           -40.70179509236059],
                                                           [-18.6000000672,
                                                           -39.464994178287064],
                                                           [-20.00000007,
                                                           -38.838189880150665],
                                                           [-21.4000000728,
                                                           -39.464994178287064],
                                                           [-21.4000000728,
                                                           -40.70179509236059],
                                                           [-20.00000007,
                                                           -41.31174966478728]]],
                                           'type': 'Polygon'},
                              'id': '-0.3490658516205964,-0.7648749219440846',
                              'type': 'Feature'},
                             {'geometry': {'coordinates': [[[-20.00000007,
                                                           -37.56790013078226],
                                                           [-18.6000000672,
                                                           -36.924474103794715],
                                                           [-18.6000000672,
                                                           -35.62123099996148],
                                                           [-20.00000007,
                                                           -34.96149172026768],
                                                           [-21.4000000728,
                                                           -35.62123099996148],
                                                           [-21.4000000728,
                                                           -36.924474103794715],
                                                           [-20.00000007,
                                                           -37.56790013078226]]],
                                           'type': 'Polygon'},
                              'id': '-0.3490658516205964,-0.6802309514438665',
                              'type': 'Feature'},
                             {'geometry': {'coordinates
...

要选择指定边界内的hexbins,我们可以从plotly生成的fig.data[0]中的customdata和geojson中提取信息,并创建一个geopandas Dataframe 。然后我们可以创建一个新的geopandas Dataframe ,称为hexbins_in_afr,它是hexbins的新gdf和Afr_gdf_area之间的内部连接(以便我们删除Afr_gdf_area之外的所有hexbins)。
在我们从hexbins_in_afrcustomdata中提取geojson信息之后,我们可以在fig.data[0]中显式设置以下字段:

fig.data[0]['geojson']['features'] = new_geojson
fig.data[0]['customdata'] = hexbins_in_afr['customdata']

下面是经过必要修改的代码:

import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objs as go
import plotly.figure_factory as ff
import geopandas as gpd
from geopandas.tools import sjoin
from shapely.geometry import Polygon
import json

data = pd.DataFrame({
    'LAT': [1,5,6,7,5,6,7,5,6,7,5,6,7,12,-40,50],
    'LON': [10,10,11,12,10,11,12,10,11,12,10,11,12,-20,40,50],
    })

gdf_poly = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
gdf_poly = gdf_poly.drop('name', axis = 1)

Afr_gdf_area = gdf_poly[gdf_poly['continent'] == 'Africa'].reset_index(drop = True)

fig = ff.create_hexbin_mapbox(data_frame=data,
                       lat="LAT", 
                       lon="LON",
                       nx_hexagon=25,
                       opacity=0.4,
                       labels={"color": "Point Count"},
                       mapbox_style='carto-positron',
                       zoom = 1
                       )

gdf = gpd.GeoDataFrame({
    'customdata': fig.data[0]['customdata'].tolist(),
    'id':[item['id'] for item in fig.data[0]['geojson']['features']],
    'geometry':[Polygon(item['geometry']['coordinates'][0]) for item in fig.data[0]['geojson']['features']]
})
gdf.set_crs(epsg=4326, inplace=True)

hexbins_in_afr = sjoin(gdf, Afr_gdf_area, how='inner')

def get_coordinates(polygon):
    return [[list(i) for i in polygon.exterior.coords]]

hexbins_in_afr['coordinates'] = hexbins_in_afr['geometry'].apply(lambda x: get_coordinates(x))

## create a new geojson that matches the structure of fig.data[0]['geojson']['features']
new_geojson = [{
    'type': 'Feature', 
    'id': id, 
    'geometry': {
        'type': 'Polygon', 
        'coordinates': coordinate
    }
} for id, coordinate in zip(hexbins_in_afr['id'],hexbins_in_afr['coordinates'])]

fig.data[0]['geojson']['features'] = new_geojson
fig.data[0]['customdata'] = hexbins_in_afr['customdata']

fig.update_layout(mapbox={
        "layers": [
            {"source": json.loads(Afr_gdf_area.geometry.to_json()),
                "below": "traces",
                "type": "fill",
                "color": "orange",
                "opacity" : 0.1,
                "line": {"width": 1}
            },
        ],
    })   

fig.show()

相关问题