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

问题描述 投票:0回答:1

我正在绘制一个单独的 hexbin 图和 json 边界文件。尽管 hexbin 网格与边界文件重叠。我只对展示非洲大陆感兴趣。我的目标是切断或子集 hexbin 网格within 非洲大陆。因此不应在边界文件之外显示任何网格正方形。有没有办法使用 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()

预期的输出是切断或剪掉非洲满足感之外的方块,这是橙色的。

python json plotly
1个回答
0
投票

如果你往里面看

fig.data[0]
,它是一个
Choroplethmapbox
,有几个字段,包括
customdata
geojson
。 geojson 包含绘制 hexbins 所需的所有信息,包括坐标和每个六边形的唯一
id
。 customdata 是一个形状为
[n_hexbins x 3]
的数组,其中数组的每个元素都包含 id 和用于绘制确定每个 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 数据框。然后我们可以创建一个名为

hexbins_in_afr
的新 geopandas 数据框,它是我们新的 hexbin 的 gdf 和
Afr_gdf_area
之间的内部连接(这样我们就可以删除 Afr_gdf_area 之外的所有 hexbin)。

我们从

geojson
hexbins_in_afr
中提取
customdata
信息后,我们可以在
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()

© www.soinside.com 2019 - 2024. All rights reserved.