通过reticulate调用tslearn的TimeSeriesKMeans遇TypeError求助
问题排查:R通过reticulate调用tslearn.TimeSeriesKMeans报错TypeError
报错场景
使用reticulate将R的data.frame转换为numpy数组后,调用tslearn的TimeSeriesKMeans.fit()时触发错误:
TypeError: 'float' object cannot be interpreted as an integer
从Python报错栈可以定位到,错误发生在tslearn创建聚类中心数组的步骤:
centers = numpy.empty((n_clusters, n_timestamps, n_features), dtype=X.dtype)
其中n_timestamps或n_features被识别为浮点数类型,而numpy创建数组要求维度参数必须是整数。
根本原因
- 维度结构不匹配:tslearn要求输入的时间序列数组需为3维结构:
(样本数, 时间步长, 特征数),即使是单变量时间序列(仅1个特征),也需要显式保留特征维度。当前转换后的numpy数组是2维的(样本数, 时间步长),导致tslearn解析维度时出现类型偏差。 - 冗余转换操作:代码中
r_to_py(np$array(time_series))属于冗余操作,reticulate已实现R对象到Python对象的自动转换,重复调用反而可能引入类型转换问题,导致维度值被解析为浮点数。
修复方案
方案1:在R中直接生成3维数组
修改数组转换步骤,显式增加特征维度:
# 直接将data.frame转换为numpy数组,无需额外r_to_py调用 np <- reticulate::import("numpy") ts_np <- np$array(time_series) # 增加特征维度,从(6,11)变为(6,11,1) ts_np <- ts_np[,, np$newaxis]
方案2:使用tslearn工具函数转换格式
去掉冗余转换,直接传入R对象,再通过tslearn的预处理函数调整维度:
# 直接传入R的data.frame,reticulate自动转为numpy数组 ts_np <- time_series # 使用tslearn工具函数将2维数组转为符合要求的3维格式 ts_preprocess <- reticulate::import("tslearn.preprocessing") ts_np_3d <- ts_preprocess$TimeSeriesResampler(sz=length(time))$fit_transform(ts_np)
完整修复代码示例
library(reticulate) library(magrittr) reticulate::py_install(c("numpy", "pandas", "tslearn")) # 模拟节律时间序列 time <- seq(1, 21, 2) time_series <- lapply(seq(0, 1, .2), function(x) x*sin(2*pi*time/24)) %>% unlist %>% matrix(., byrow=TRUE, ncol=length(time)) %>% data.frame %>% setNames(paste0("time", time)) # 转换为符合要求的3维numpy数组 np <- reticulate::import("numpy") ts_np <- np$array(time_series)[,, np$newaxis] # 调用TimeSeriesKMeans并训练 ts <- reticulate::import("tslearn.clustering") tsk <- ts$TimeSeriesKMeans(n_clusters=2, metric="dtw") tsk$fit(ts_np) # 查看聚类结果 tsk$labels_
额外注意事项
- 避免在reticulate中重复调用
r_to_py和np$array,依赖自动转换即可减少类型问题。 - tslearn对输入维度要求严格,单变量时间序列必须保持3维结构,多变量需遵循
(样本数, 时间步长, 特征数)的格式。
内容的提问来源于stack exchange,提问作者ATpoint
相关产品推荐
相关产品推荐

