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

环形周期客流量数据的Python聚类实现方案问询

环形周期数据的Python聚类方案

针对你提到的餐厅夜店客流量的时间周期数据(23点与0点连续),以下是几个可落地的Python聚类方案:

方案1:映射到二维单位圆 + 常规聚类算法

把一维环形时间数据转换成二维平面的单位圆坐标,让周期连续性被常规算法识别,之后用GMM/K-Means都可实现,支持指定聚类数。

实现步骤:

  1. 将时间(0-23)转换为弧度:theta = (time / 24) * 2 * np.pi(用24确保0和24/23点对应圆上同一位置)
  2. 计算二维坐标:x = np.cos(theta), y = np.sin(theta)
  3. 用sklearn的GaussianMixture或KMeans执行聚类
  4. 将聚类中心的二维坐标转换回原时间维度

代码示例:

import numpy as np
from sklearn.mixture import GaussianMixture

# 模拟围绕0和12.5分布的环形数据
np.random.seed(42)
data = np.concatenate([np.random.normal(0, 1, 200), np.random.normal(12.5, 1, 200)])
data = np.mod(data, 24)  # 处理超出0-23的数值

# 转换为单位圆坐标
theta = (data / 24) * 2 * np.pi
x = np.cos(theta)
y = np.sin(theta)
X = np.column_stack([x, y])

# 指定2个聚类,用GMM拟合
gmm = GaussianMixture(n_components=2, random_state=42)
labels = gmm.fit_predict(X)

# 将聚类中心转回时间维度
centers_theta = np.arctan2(gmm.means_[:, 1], gmm.means_[:, 0])
centers_time = (centers_theta % (2 * np.pi)) * 24 / (2 * np.pi)
print("聚类中心时间:", centers_time)  # 输出接近0和12.5

方案2:环形高斯混合模型(基于冯·米塞斯分布)

冯·米塞斯(Von Mises)分布是正态分布在环形数据上的等价形式,直接用该分布构建混合模型,更贴合周期数据特性。支持通过BIC准则自动选择聚类数。

代码示例(手动拟合双组件Von Mises混合模型):

import numpy as np
from scipy.stats import vonmises
from scipy.optimize import minimize

# 将数据转换为0-2π的弧度
data_rad = (data / 24) * 2 * np.pi

# 定义混合模型的负对数似然函数
def neg_log_likelihood(params):
    mu1, kappa1, mu2, kappa2, weight = params
    # 约束权重在0-1区间
    if weight < 0 or weight > 1:
        return np.inf
    ll = np.log(weight * vonmises.pdf(data_rad, kappa1, loc=mu1) + 
                (1 - weight) * vonmises.pdf(data_rad, kappa2, loc=mu2))
    return -np.sum(ll)

# 初始参数:mu对应0和12.5的弧度,kappa为浓度参数(类似正态分布方差的倒数)
init_params = [0, 5, (12.5/24)*2*np.pi, 5, 0.5]
result = minimize(neg_log_likelihood, init_params, method='L-BFGS-B')

# 提取结果并转回时间
mu1_time = (result.x[0] % (2*np.pi)) *24/(2*np.pi)
mu2_time = (result.x[2] % (2*np.pi)) *24/(2*np.pi)
print("聚类中心时间:", mu1_time, mu2_time)

方案3:自定义环形距离的DBSCAN(无需指定聚类数)

DBSCAN是基于密度的聚类算法,无需预先指定聚类数。核心是将距离度量替换为环形距离:即两个时间点的最小间隔(比如23和0的距离为1,而非23)。

代码示例:

import numpy as np
from sklearn.cluster import DBSCAN

# 自定义环形距离函数
def circular_distance(a, b):
    return np.minimum(np.abs(a - b), 24 - np.abs(a - b))

# 用DBSCAN聚类,调整eps和min_samples控制聚类效果
dbscan = DBSCAN(eps=1.5, min_samples=5, metric=circular_distance)
labels = dbscan.fit_predict(data.reshape(-1, 1))

# 计算每个聚类的环形均值作为中心
unique_labels = np.unique(labels[labels != -1])
cluster_centers = []
for label in unique_labels:
    cluster_data = data[labels == label]
    rad = (cluster_data /24)*2*np.pi
    mean_rad = np.arctan2(np.mean(np.sin(rad)), np.mean(np.cos(rad)))
    mean_time = (mean_rad % (2*np.pi)) *24/(2*np.pi)
    cluster_centers.append(mean_time)
print("聚类中心时间:", cluster_centers)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 20:22:51