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

如何在Python Shiny应用的Highcharts热力图单元格内用圆形替代方块

问题描述

我正在开发Python Shiny应用,已创建了一个接近需求的热力图。但我希望每个单元格不是方块,而是在方块内包含一个圆形,效果如下:

当前效果:
热力图当前效果

目标效果:
热力图目标效果

以下是我的Highcharts热力图相关代码:

# 配置部分
options = {
    'chart': {
        #'type': 'heatmap',
        'plotBorderWidth': 1,
        'width': 1500,
        'height': 800,
    },
    'title': {'text': postes},
    'xAxis': {
        'categories': categories_x,
        'title': {'text': ''}
    },
    'yAxis': {
        'categories': categories_y,
        'title': {'text': ''},
        'reversed': True,
        'labels': {'useHTML': True}
    },
    'legend': {'enabled': False},
    'series': [
        {
            'type': 'heatmap',
            'name': 'État EVT',
            #'borderWidth': 1,
            #'borderColor': 'black',
            'data': heatmap_data,
            'dataLabels': {'enabled': False}
        },
        {
            'type': 'scatter',
            'name': 'Alertes',
            'data': icons_to_add,
            'marker': {
                'symbol': 'url(https://cdn-icons-png.flaticon.com/512/80/80795.png)',
                'width': 20,
                'height': 20
            },
            'enableMouseTracking': False
        }
    ],
    'boost': {'enabled': True},
}
plot_lines = []
for i in range(len(categories_y) - 1):
    plot_lines.append({
        'color': '#cccccc',
        'width': 1,
        'value': i + 0.5,
        'zIndex': 5
    })

options['yAxis']['plotLines'] = plot_lines
options_json = json.dumps(options, ensure_ascii=False)

# Shiny输出部分
@output
@render.ui
def hc_container_heatmap():
    options_json, dict_lien_ged_json, _, styled_df = donnees_compilees()
    return ui.HTML(f"""
        <div id="hc_container_heatmap" style="margin-bottom: 20px;"></div>
        <script type="text/javascript">
            if (typeof Highcharts !== 'undefined') {{
                const options = {options_json};
                const categoryLinks = {dict_lien_ged_json};

                options.yAxis.labels.formatter = function() {{
                    const category = this.value;
                    const link = categoryLinks[category];
                    if (link) {{
                        return '<a href="' + link + '" target="_blank">' + category + '</a>';
                    }} else {{
                        return category;
                    }}
                }};
                Highcharts.chart('hc_container_heatmap', options);
            }} else {{
                console.error("Highcharts non chargé");
            }}
        </script>
    """)

请问是否可以修改Highcharts(或同类工具)的配置实现该效果?或者有没有更优方案,在Python Shiny中用同一数据集渲染该图形?


解决方案

方案1:修改Highcharts热力图配置,用Marker实现圆形

直接改造现有热力图系列,隐藏默认方块填充,改用圆形marker,并保留网格线:

  1. 修改热力图系列配置:
{
    'type': 'heatmap',
    'name': 'État EVT',
    'data': heatmap_data,
    'dataLabels': {'enabled': False},
    # 隐藏默认方块填充
    'color': 'transparent',
    'borderWidth': 0,
    # 配置居中显示的圆形marker
    'marker': {
        'enabled': True,
        'symbol': 'circle',
        'radius': 15,  # 根据需求调整圆形大小
        'lineWidth': 1,
        'lineColor': '#333'
    },
    'pointPlacement': 'on'
}
  1. 给每个数据点添加动态颜色(可选):在heatmap_data的每个元素中加入color字段,比如{'x': 0, 'y': 0, 'value': 10, 'color': '#ff4500'}
  2. 补充x轴网格线:
options['xAxis']['plotLines'] = [
    {'color': '#cccccc', 'width': 1, 'value': i + 0.5, 'zIndex': 5} 
    for i in range(len(categories_x) - 1)
]

方案2:用Scatter系列完全替代热力图

如果热力图配置限制较多,直接用散点系列绘制圆形,搭配网格线模拟热力图布局:

  1. 移除原热力图系列,修改散点系列配置:
'series': [
    {
        'type': 'scatter',
        'name': 'État EVT',
        'data': heatmap_data,
        'marker': {
            'symbol': 'circle',
            'radius': 15,
            'lineWidth': 1,
            'lineColor': '#333'
        },
        'pointPlacement': 'on'
    },
    # 保留原告警图标系列
    {
        'type': 'scatter',
        'name': 'Alertes',
        'data': icons_to_add,
        'marker': {
            'symbol': 'url(https://cdn-icons-png.flaticon.com/512/80/80795.png)',
            'width': 20,
            'height': 20
        },
        'enableMouseTracking': False
    }
]
  1. 保留x、y轴的plotLines来生成网格,配置同方案1。

方案3:用Plotly在Python Shiny中实现

无需编写JS代码,直接用Plotly的散点图实现,配置更简洁:

import plotly.graph_objects as go
from shiny import App, render, ui

def create_circle_heatmap(categories_x, categories_y, heatmap_data):
    x = [p['x'] for p in heatmap_data]
    y = [p['y'] for p in heatmap_data]
    colors = [p['color'] for p in heatmap_data]
    
    fig = go.Figure()
    fig.add_trace(go.Scatter(
        x=x, y=y,
        mode='markers',
        marker=dict(
            size=30, color=colors,
            symbol='circle',
            line=dict(width=1, color='#333')
        )
    ))
    
    fig.update_layout(
        xaxis=dict(
            tickmode='array',
            tickvals=list(range(len(categories_x))),
            ticktext=categories_x,
            showgrid=True, gridcolor='#cccccc'
        ),
        yaxis=dict(
            tickmode='array',
            tickvals=list(range(len(categories_y))),
            ticktext=categories_y,
            showgrid=True, gridcolor='#cccccc',
            autorange='reversed'
        ),
        width=1500, height=800,
        showlegend=False
    )
    return fig

# Shiny输出部分
@output
@render.plotly
def circle_heatmap():
    _, _, _, styled_df = donnees_compilees()
    # 替换为实际数据逻辑
    categories_x = [...]
    categories_y = [...]
    heatmap_data = [...]
    return create_circle_heatmap(categories_x, categories_y, heatmap_data)

内容的提问来源于stack exchange,提问作者AnonX

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 01:20:54