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

Python实现聚类大小随数据点数量变化并标注聚类数量

解决方案:手动聚类后实现按需可视化

你的问题核心在于:Plotly的自动聚合(cluster=dict(enabled=True))只是视觉上合并点,但size参数绑定的是原始单个数据点的字段值,而非聚类内的总点数。要实现「聚类大小随内部点数变化+标注点数」的需求,必须先手动完成聚类计算,再基于聚类结果绘图。以下提供两种适配学术论文场景的方案:

方案一:静态学术图(Matplotlib + Cartopy + Scikit-learn)

适合需要无交互、可直接插入论文的静态地图,Cartopy是地理绘图的专业工具,Scikit-learn负责聚类计算。

代码示例

import pandas as pd
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from sklearn.cluster import DBSCAN
import numpy as np

# 1. 加载数据
df = pd.read_csv(
    "https://raw.githubusercontent.com/plotly/datasets/master/2011_february_us_airport_traffic.csv"
)
coords = df[['lat', 'long']].values

# 2. 地理点聚类(DBSCAN,适合密度聚类,适配WGS84经纬度)
coords_rad = np.radians(coords)
# eps=0.01 对应约1110米的聚类半径(可根据需求调整),min_samples=2表示至少2个点成簇
db = DBSCAN(eps=0.01, min_samples=2, metric='haversine').fit(coords_rad)
df['cluster_label'] = db.labels_

# 3. 计算每个聚类的统计量:中心经纬度、点数
cluster_stats = df.groupby('cluster_label').agg(
    lat_center=('lat', 'mean'),
    lon_center=('long', 'mean'),
    point_count=('lat', 'count')
).reset_index()
# 过滤噪声点(label=-1)
cluster_stats = cluster_stats[cluster_stats['cluster_label'] != -1]

# 4. 绘制静态地图
plt.figure(figsize=(12, 8))
# 用PlateCarree投影适配WGS84坐标系
ax = plt.axes(projection=ccrs.PlateCarree())
ax.coastlines()
ax.stock_img()  # 添加基础地图底图

# 绘制聚类:大小与点数正相关(这里乘以50是缩放系数,可调整)
scatter = ax.scatter(
    cluster_stats['lon_center'],
    cluster_stats['lat_center'],
    s=cluster_stats['point_count'] * 50,
    c='red',
    alpha=0.7,
    transform=ccrs.PlateCarree()
)

# 标注聚类点数
for idx, row in cluster_stats.iterrows():
    ax.text(
        row['lon_center'],
        row['lat_center'],
        str(row['point_count']),
        fontsize=10,
        ha='center',
        va='center',
        transform=ccrs.PlateCarree()
    )

plt.title('Airport Traffic Clusters (Point Count-Sized)', fontsize=14)
plt.tight_layout()
plt.savefig('cluster_map.png', dpi=300, bbox_inches='tight')  # 导出高清图用于论文
plt.show()

关键说明

  • 用DBSCAN密度聚类:适合地理数据,能自动识别不同密度的簇,无需预设簇数量;若需固定簇数,可替换为KMeans
  • 聚类大小通过s=cluster_stats['point_count'] * 缩放系数直接绑定点数,完全可控
  • 导出的PNG/SVG可直接用于学术论文,无交互依赖

方案二:Plotly静态导出方案(先聚类再绘图)

若偏好Plotly的视觉风格,可先手动聚类,再绘制聚类中心,最后导出为静态图。

代码示例

import plotly.express as px
import pandas as pd
from sklearn.cluster import DBSCAN
import numpy as np

px.set_mapbox_access_token(open(".mapbox_token").read())
df = pd.read_csv(
    "https://raw.githubusercontent.com/plotly/datasets/master/2011_february_us_airport_traffic.csv"
)

# 1. 同方案一:完成聚类计算
coords = df[['lat', 'long']].values
coords_rad = np.radians(coords)
db = DBSCAN(eps=0.01, min_samples=2, metric='haversine').fit(coords_rad)
df['cluster_label'] = db.labels_

cluster_stats = df.groupby('cluster_label').agg(
    lat_center=('lat', 'mean'),
    lon_center=('long', 'mean'),
    point_count=('lat', 'count')
).reset_index()
cluster_stats = cluster_stats[cluster_stats['cluster_label'] != -1]

# 2. 绘制聚类中心,size绑定点数,text标注点数
fig = px.scatter_mapbox(
    cluster_stats,
    lat="lat_center",
    lon="lon_center",
    size="point_count",
    text="point_count",
    zoom=3,
    size_max=100,  # 限制最大点大小,避免过度放大
    color_discrete_sequence=["red"]
)
fig.update_traces(textposition='middle center')
fig.update_layout(mapbox_style='carto-positron')  # 学术风格的简洁底图

# 导出为静态PNG/SVG用于论文(需提前安装kaleido:pip install kaleido)
fig.write_image('plotly_cluster_map.png', scale=3)
fig.show()

关键说明

  • 放弃Plotly的自动聚类功能,改用手动聚类结果,确保size参数绑定的是聚类总点数
  • 用write_image导出高清静态图,满足学术论文需求

内容的提问来源于stack exchange,提问作者César Leblanc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 14:53:24