python - 从 pandas 数据框创建 plotly scattermapbox
问题描述
我想为印度尼西亚的各种统计数据(人口、GDP 等)在区域基础上创建一个散点图框。我正在使用来自github的 geopandas 文件。
plotly 网站上的示例为每一层创建多个文件,然后使用 github 链接作为源。
#republican counties
source = 'https://raw.githubusercontent.com/plotly/datasets/master/florida-red-data.json'
#democrat counties
source = 'https://raw.githubusercontent.com/plotly/datasets/master/florida-blue-data.json'
因此,我的问题是,如何使用 pandas 数据框为每个区域创建图层字典并将其用作源(也可以通过其他数据框中的特定值对每个区域进行着色)。如果这根本不可能,并且有必要为每个区域创建一个单独的文件,我该怎么做?我的尝试(第 16-20 行)似乎不起作用
import pandas as pd
import json
import string
import plotly
from plotly.graph_objs import Scattermapbox, Layout
ID_regions = pd.read_json('https://raw.githubusercontent.com/N1x0/indonesia-geojson/master/indonesia-edit.geojson')
region_names = []
for region in ID_regions['features']:
region_names.append(state['properties']['name'])
print(region_names)
#This shit creates json and doesn't work
def create_region_files():
for i in range(len(ID_regions)):
region_data = ID_regions.iloc[i,:]
region_data.to_json(f'C:\\Users\\nicho\\Desktop\\Waste Management\\Map_Maker\\ID_regions\\{region_names[i]}.json')
i += 1
def create_Chloropleth():
mapbox_access_token = 'My Access Key'
data = [
Scattermapbox(
lat=['45.5017'],
lon=['-73.5673'],
mode='markers',
)
]
layout = Layout(
height=900,
autosize=True,
showlegend=False,
hovermode='closest',
mapbox=dict(
layers=[
dict(
sourcetype = 'geojson',
source = 'https://raw.githubusercontent.com/N1x0/indonesia-geojson/master/indonesia-edit.geojson',
type = 'fill',
color = 'green'
),
dict(
sourcetype = 'geojson',
source = 'https://raw.githubusercontent.com/N1x0/indonesia-geojson/master/west-sulawesi.json',
type = ' fill',
color = 'red',
)
],
accesstoken=mapbox_access_token,
bearing=0,
center=dict(
lat=0.7893,
lon=113.9213
),
pitch=0,
zoom=4.5,
style='light'
),
)
fig = dict(data=data, layout=layout)
plotly.offline.plot(fig, filename='Chloropleth_Province_Population.html')
create_Chloropleth()
感谢您的帮助!
解决方案
好吧,我花了一段时间,但我想通了。非常感谢Medium 和Vince Pota的Emma Grimaldi。他们的帖子帮助我度过了大部分时间。所以这里按顺序回答我自己的问题:
- 不必为每个区域创建单独的文件。即,您可以使用 pandas 数据框来匹配 json 中区域的名称,这样就可以了。
with open('indonesia-en.geojson') as f:
geojson = json.load(f)
def make_sources(downsample = 0):
sources = []
geojson_copy = copy.deepcopy(geojson['features']) # do not overwrite the original file
for feature in geojson_copy:
if downsample > 0:
coords = np.array(feature['geometry']['coordinates'][0][0])
coords = coords[::downsample]
feature['geometry']['coordinates'] = [[coords]]
sources.append(dict(type = 'FeatureCollection',
features = [feature])
)
return sources
因此,您只需从 geojson 中提取坐标并将它们附加到 dicts 列表中[{}]
。
- 如何使用此列表动态创建图层:
MAPBOX_APIKEY = "Your API Key"
data = dict(type='scattermapbox',
lat=lats,
lon=lons,
mode='markers',
text=hover_text,
marker=dict(size=1,
color=scatter_colors,
showscale = True,
cmin = minpop/1000000,
cmax = maxpop/1000000,
colorscale = colorscale,
colorbar = dict(
title='Population in Millions'
)
),
showlegend=False,
hoverinfo='text'
)
layers=([dict(sourcetype = 'geojson',
source =sources[k],
below="water",
type = 'line', # the borders
line = dict(width = 1),
color = 'black',
) for k in range(n_provinces) # where n_provinces = len(geojson['features'])
] +
[dict(sourcetype = 'geojson',
source =sources[k],
type = 'fill', # the area inside the borders
color = scatter_colors[k],
opacity=0.8
) for k in range(n_provinces) # where n_provinces = len(geojson['features'])
]
)
所以这里的解决方案太设置 sources = sources[k]
了,即带有在中创建的 lat/long 值的字典的列表make_sources()
- 如何相应地为图层着色
color=scatter_colors[k]
使用链接的示例,我使用了 3 个函数
3.1 scalarmappable
#sets colors based on min and max values
def scalarmappable(cmap, cmin, cmax):
colormap = cm.get_cmap(cmap)
norm = Normalize(vmin=cmin, vmax=cmax+(cmax*0.10)) #vmax get's increased 10 percent because otherwise the most populous region doesnt get colored
return cm.ScalarMappable(norm=norm, cmap=colormap)
3.2scatter_colors
#uses matplotlib to create colors based on values and sets grey for isnan value
def get_scatter_colors(sm, df):
grey = 'rgba(128,128,128,1)'
return ['rgba' + str(sm.to_rgba(m, bytes = True, alpha = 1)) if not np.isnan(m) else grey for m in df]
3.3colorscale
#defines horizontal range and corresponding values for colorscale
def get_colorscale(sm, df, cmin, cmax):
xrange = np.linspace(0, 1, len(df))
values = np.linspace(cmin, cmax, len(df))
return [[i, 'rgba' + str(sm.to_rgba(v, bytes = True))] for i,v in zip(xrange, values) ]
然后设置使用函数的变量
#assigning values
colormap = 'nipy_spectral'
minpop = stats['population'].min()
maxpop = stats['population'].max()
sources = make_sources(downsample=0)
lons, lats = get_centers()
sm = scalarmappable(colormap, minpop, maxpop)
scatter_colors = get_scatter_colors(sm, stats['population'])
colorscale = get_colorscale(sm, stats, minpop, maxpop)
hover_text = get_hover_text(stats['population'])
因此,如果有人对此答案有疑问,可以帮助您取得进步:)
推荐阅读
- arduino - 在 Arduino 和 ESP8266 之间处理 GET 请求
- azure-active-directory - 使用图形管理 Windows 虚拟桌面的应用程序组
- javascript - TypeError:无法读取未定义的属性“qtt”
- json - 用数组而不是字典解码 JSON 对象
- google-cloud-platform - BigQuery 中的政策标签
- tensorflow - TensorFlow 对象检测 API 仅使用 CPU 和崩溃
- reactjs - React-Redux,在组件初始渲染上更新存储
- javascript - 从 ID 数组中获取数据的正确方法?
- javascript - Photoshop Extendscript - 文件被锁定 - 无法保存
- discord.js - 如何创建 discord.js ping 命令?