有没有办法调整使用 Plotly 创建的离散 choropleth 的图例项的大小?

Posted

技术标签:

【中文标题】有没有办法调整使用 Plotly 创建的离散 choropleth 的图例项的大小?【英文标题】:Is there a way to resize the legend items of a discrete choropleth created using Plotly? 【发布时间】:2022-01-07 09:47:35 【问题描述】:

如果有帮助,我正在使用 Python,但我相信任何解决方案都与语言无关。我使用 plotly.express 创建了一个离散的 choropleth 地图框,但是当以高分辨率导出时,图例项(字体和颜色)实际上变得不可读。如果我记得,Plotly 通过叠加多条迹线来创建离散图形,因此不确定我们是否可以在迹线或图形级别进行修复。

如果有帮助,很乐意分享代码,尽管我实际上还没有更新图例,所以我认为它不会添加任何东西。

Hi-res map output

Std map output

代码:

DISCRETE = 11

def gen_colorscale(obs, color="viridis"):
    color = px.colors.sample_colorscale(color, obs)
    p1 = tuple(zip(np.linspace(0, 1, obs+1)[:-1], color))
    p2 = tuple(zip(np.linspace(0, 1, obs+1)[1:], color))
    cs = []
    for a, b in zip(p1, p2):
        cs.append(a)
        cs.append(b)
    return cs

cs = gen_colorscale(DISCRETE)

# color range
cr = [0, 10000]
# tick vals
v = np.linspace(*cr, DISCRETE)
vt = (
    pd.DataFrame(v, columns=["v"])
    .apply(lambda v: (v / 10 ** 3).round(1))
    .apply(lambda v: v.astype(str) + "k to " + v.shift(-1).astype(str) + "k")
    .values
)
vt[0] = v[0].astype(str) + " to " + (v[1] / 10 ** 3).round(1).astype(str) + "k"
vt[-1] = ">" + (v[-1] / 10 ** 3).round(1).astype(str) + "k"

fig = px.choropleth_mapbox(
    df,
    geojson=counties,
    locations="fips",
    color="migration",
    range_color=[cr[0], cr[1] + cr[1]/(DISCRETE-1)],
    color_continuous_scale=cs,
    labels="migration": "Migration (k)",
    center="lat": 37.0902, "lon": -95.7129,
    zoom=4.2,
    opacity=1.0,
    mapbox_style="white-bg",
)
fig.update_layout(
    mapbox_style="mapbox://styles/ryangilland/ckwqzs8ck0h5f14nybww9c5ts",
    mapbox_accesstoken=token,
    coloraxis_colorbar=dict(
        tickvals=np.linspace(cr[0]+cr[1]/(DISCRETE-1)/2,cr[1] + cr[1]/(DISCRETE-1)/2,DISCRETE),
        ticktext=vt,
        len=0.8,
        thickness=50,
        xanchor="right",
        x=1.0,
        bgcolor="rgba(22,33,49,1)",
        tickfont=dict(color="rgba(255,255,255,1)"),
    ),
    margin=dict(l=0, r=0, b=50, t=75, pad=4),
    paper_bgcolor="rgba(8,18,23,1)",
    plot_bgcolor="rgba(8,18,23,1)",
)
fig.show()

Sample Image

【问题讨论】:

【参考方案1】: 以另一种方式看待这个问题。 https://plotly.com/python/colorscales/#constructing-a-discrete-or-discontinuous-color-scale 因此您可以使用离散桶来创建色标 然后我希望这在高分辨率屏幕上效果很好,因为彩条使用整个屏幕高度 如果不需要使用 tickvalsticktext 解决方案要简单得多
import geopandas as gpd
import numpy as np
import pandas as pd
import plotly.express as px

gdf = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres")).set_index("iso_a3")

DISCRETE = 6
# build discrete continuous colorscale
cs = [
    (a, px.colors.sample_colorscale("viridis", b)[0])
    for a, b in zip(
        np.repeat(np.linspace(0, 1, DISCRETE + 1), 2)[1:-1],
        np.repeat(np.linspace(0, 1, DISCRETE + 1), 2),
    )
]
# color range
cr = [0, gdf["pop_est"].quantile(.95)]
# tick vals
v = np.linspace(*cr, DISCRETE+1)
vt = (
    pd.DataFrame(v, columns=["v"])
    .apply(lambda v: (v / 10 ** 6).round(0).astype(int))
    .apply(lambda v: v.astype(str) + "M to " + v.shift(-1).astype(str) + "M")
    .values
)
px.choropleth_mapbox(
    gdf,
    geojson=gdf.__geo_interface__,
    locations=gdf.index,
    color="pop_est",
    color_continuous_scale=cs,
    range_color=cr,
).update_layout(
    mapbox="style": "carto-positron", "zoom": .5,
    coloraxis="colorbar": "tickvals": v[1:] - v[1]/2, "ticktext":vt,
    margin="l":0,"r":0,"t":0,"b":0
)

【讨论】:

这很有帮助!只是在此基础上构建,因为这在某种程度上是一种伪装的连续比例,是否有一个颜色范围是单点的?例如,如果我只想为等于 0 的条目设置一种颜色,然后为 >0 和 130.0M”桶。我将当前代码添加到原始代码中,这有助于生成我添加的图像(阿拉斯加和夏威夷分别添加并粘贴到我的脚本中),

以上是关于有没有办法调整使用 Plotly 创建的离散 choropleth 的图例项的大小?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Plotly 创建具有 n 个颜色的离散颜色图

如何让 Plotly 根据 Streamlit 应用程序中的屏幕分辨率调整绘图大小?

plotly.js,如何调整标题区域大小

有没有办法用 plotly 或 python 创建条形图可视化,其中 y 轴是 24 小时范围,x 轴是所有工作日?

有没有办法在 R 中创建 Plotly 图表的全屏弹出窗口?

有没有办法使用 plotly 开始一个已经在特定区域放大的情节?