You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Plotly Express Scatter Mapbox设置animation_frame后分类缺失问题求助

Plotly Express Scatter Mapbox设置animation_frame后分类缺失问题求助

大家好,我最近在用Plotly Express的px.scatter_mapbox做客户分布的地图散点图,需求是:

  • 用brand_name作为动画帧,切换展示不同品牌
  • 每个品牌的帧里,用不同颜色区分该品牌下的各个purchasing_model_y(车型)
  • 点的大小对应count_customers(客户数量)

但我遇到了一个棘手的问题:只要设置了animation_frame='brand_name',每个帧里就只会显示一种车型;如果不设置动画帧,所有品牌的所有车型都能正常显示。因为品牌和车型数量较多,必须用动画帧来分类梳理,所以想请教大家怎么解决这个问题?

我已经做了以下尝试,下面是我的测试数据和实现代码:

测试数据构造

import pandas as pd

data = {'brand_name': ['BMW', 'BMW', 'BMW', 'Mercedes', 'Mercedes', 'Mercedes'],
        'purchasing_model_y': ['X1', 'X2', 'X3', 'C-Class', 'E-Class', 'S-Class'],
        'lat': [52.5200, 52.5200, 52.5200, 48.1351, 48.1351, 48.1351],
        'long': [13.4050, 13.4050, 13.4050, 11.5820, 11.5820, 11.5820],
        'count_customers': [10, 20, 30, 15, 25, 35]}

full_df4 = pd.DataFrame(data)

绘图代码

import plotly.express as px

# zoom和center是通过下面的自定义函数计算得到的
fig = px.scatter_mapbox(full_df4, lat="lat", lon="long", color='purchasing_model_y', size='count_customers',
                        animation_frame='brand_name',
                        zoom=zoom, center=center,
                        size_max=40, hover_name='community_name',  # 注:community_name是我实际数据集里的字段,测试数据中未包含
                        height=600, width=1000, title='Allocation of Customers by Car Brand and Model ', mapbox_style="open-street-map")

fig.update_layout(font_size=16, title_font_size=24, mapbox_accesstoken=api_token)

计算zoom和center的自定义函数

import numpy as np

def zoom_center(lons: tuple=None, lats: tuple=None, lonlats: tuple=None,
                format: str='lonlat', projection: str='mercator',
                width_to_height: float=2.0) -> (float, dict):
    """Finds optimal zoom and centering for a plotly mapbox.
    Must be passed (lons & lats) or lonlats.
    Temporary solution for optimal map positioning.

    Parameters
    ----------
    lons: tuple, optional, longitude component of each location
    lats: tuple, optional, latitude component of each location
    lonlats: tuple, optional, gps locations
    format: str, specifying the order of longitude and latitude dimensions,
        expected values: 'lonlat' or 'latlon', only used if passed lonlats
    projection: str, only accepting 'mercator' at the moment,
        raises `NotImplementedError` if other is passed
    width_to_height: float, expected ratio of final graph's width to height,
        used to select the constrained axis.

    Returns
    --------
    zoom: float, from 1 to 20
    center: dict, gps position with 'lon' and 'lat' keys
    """
    if lons is None and lats is None:
        if isinstance(lonlats, tuple):
            lons, lats = zip(*lonlats)
        else:
            raise ValueError(
                'Must pass lons & lats or lonlats'
            )
    maxlon, minlon = max(lons), min(lons)
    maxlat, minlat = max(lats), min(lats)
    center = {
        'lon': round((maxlon + minlon) / 2, 6),
        'lat': round((maxlat + minlat) / 2, 6)
    }

    # longitudinal range by zoom level (20 to 1)
    # in degrees, if centered at equator
    lon_zoom_range = np.array([
        0.0007, 0.0014, 0.003, 0.006, 0.012, 0.024, 0.048, 0.096,
        0.192, 0.3712, 0.768, 1.536, 3.072, 6.144, 11.8784, 23.7568,
        47.5136, 98.304, 190.0544, 360.0
    ])

    if projection == 'mercator':
        margin = 1.2
        height = (maxlat - minlat) * margin * width_to_height
        width = (maxlon - minlon) * margin
        lon_zoom = np.interp(width , lon_zoom_range, range(20, 0, -1))
        lat_zoom = np.interp(height, lon_zoom_range, range(20, 0, -1))
        zoom = round(min(lon_zoom, lat_zoom), 2)
    else:
        raise NotImplementedError(
            f'{projection} projection is not implemented'
        )
    return zoom, center

有没有朋友遇到过类似的问题?或者知道怎么调整代码,让每个品牌的动画帧里显示该品牌下的所有车型?非常感谢大家的帮助!

备注:内容来源于stack exchange,提问作者xxx_anna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 14:09:50