Plotly не отображает полигоны Choropleth Mapbox - PullRequest
0 голосов
/ 05 мая 2020

Я пытался визуализировать geo JSON в Plotly путем преобразования шейп-файлов из https://geoportal.statistics.gov.uk/datasets/local-authority-districts-december-2019-boundaries-uk-bfc.

Документы Python Plotly для plotly.graph_objects.Choroplethmapbox упоминают, что в geo JSON поле id необходимо для каждой функции. Я пробовал как создать искусственное id, так и использовать поле plotly featurekeyid, но ни один из них не работает. Когда я использую ключ id, я проверял, что ключ id находится в правильном месте, и пробовал использовать как int64, так и строку.

Иногда базовый слой mapbox отображает, но не полигоны, а в других случаях код запускается, а затем зависает.

Я также попытался уменьшить размер файла .shp с помощью различных алгоритмов maphaper, затем сохранил его в формате geo JSON и пропустил этап преобразования в Python из .shp в geo JSON, но снова но безрезультатно. Кроме того, изменение tolerance в манипуляции shapely, похоже, не влияет на результат.

Я ожидаю картографическую проекцию с базовым слоем mapbox с полигонами местных органов власти сверху и с заливкой. Ссылка ниже показывает многоугольники и была создана на mapshaper.org :

Полигоны округа местных властей

Токен доступа к моему mapbox действителен.

Это пример попытки визуализировать полигоны границ местных органов власти путем добавления поля id и преобразования файла .shp в geo JSON, а затем создания трассировки:


import geopandas as gpd
from shapely.geometry import LineString, MultiLineString
import plotly.graph_objs as go

# load in shp files
lad_shp = gpd.read_file('zip://../../data/external/Local_Authority_Districts_(December_2019)_Boundaries_UK_BFC-shp.zip', encoding='utf-8')

# using empet code to convert .shp to geoJSON
def shapefile_to_geojson(gdf, index_list, tolerance=0.025): 
    # gdf - geopandas dataframe containing the geometry column and values to be mapped to a colorscale
    # index_list - a sublist of list(gdf.index)  or gdf.index  for all data
    # tolerance - float parameter to set the Polygon/MultiPolygon degree of simplification
    # returns a geojson type dict 

    geo_names = list(gdf[f'lad19nm']) # name of authorities
    geojson = {'type': 'FeatureCollection', 'features': []}
    for index in index_list:
        geo = gdf['geometry'][index].simplify(tolerance)

        if isinstance(geo.boundary, LineString):
            gtype = 'Polygon'
            bcoords = np.dstack(geo.boundary.coords.xy).tolist()

        elif isinstance(geo.boundary, MultiLineString):
            gtype = 'MultiPolygon'
            bcoords = []
            for b in geo.boundary:
                x, y = b.coords.xy
                coords = np.dstack((x,y)).tolist() 
                bcoords.append(coords) 
        else: pass



        feature = {'type': 'Feature', 
                   'id' : index,
                   'properties': {'name': geo_names[index]},
                   'geometry': {'type': gtype,
                                'coordinates': bcoords},
                    }

        geojson['features'].append(feature)
    return geojson

geojsdata = shapefile_to_geojson(lad_shp, list(lad_shp.index))

# length to generate synthetic data for z attribute
L = len(geojsdata['features'])

# check id key is there
geojsdata['features'][0].keys()
>> dict_keys(['type', 'id', 'properties', 'geometry'])

# example of authroity name
geojsdata['features'][0]['properties']['name']
>> 'Hartlepool'

# check id
k=5
geojsdata['features'][k]['id']
>> '5'

trace = go.Choroplethmapbox(z=np.random.randint(10, 75, size=L),  # synthetic data
                            locations=[geojsdata['features'][k]['id'] for k in range(L)],
                            colorscale='Viridis',
                            colorbar=dict(thickness=20, ticklen=3),
                            geojson=geojsdata,
                            text=regions,
                            marker_line_width=0.1, marker_opacity=0.7)
layout = go.Layout(title_text='UK LAD Choropleth Demo',
                   title_x=0.5,
                   width=750,
                   height=700,
                   mapbox=dict(center=dict(lat=54, lon=-2),
                               accesstoken=mapbox_access_token,
                               zoom=3))

fig=go.Figure(data=[trace], layout =layout)
fig.show()

geo JSON вывод из приведенной выше функции shapefile_to_geojson можно найти здесь: https://www.dropbox.com/s/vuf3jtrr2boq5eg/lad19-geo.json?dl=0

Кто-нибудь знает, что может быть причиной проблемы? Я предполагаю, что файлы .shp хороши, поскольку они отлично отображаются на mapshaper.org и QGis. Любая помощь будет принята с благодарностью.

Спасибо.

1 Ответ

0 голосов
/ 05 мая 2020

Простая смена системы проецирования исправила ошибку. Это нужно сделать перед преобразованием в гео JSON:

lad_shp = lad_shp.to_crs(epsg=4326)
...