如何在R语言树状图中显示标签?附聚类报错排查
问题分析与解决
错误原因
报错Error in FUN(left, right) : non-numeric argument to binary operator是因为你的CSV包含卡片编号(字符型列),读取后filedata中存在非数值数据,而compare函数里执行x1 + x2加法操作时,字符型无法参与数值运算,导致失败。
解决方案
核心思路:将卡片编号从数据列中剥离,转为行名(或单独存储),确保用于计算的数据集全为数值型;同时保留编号作为树状图的标签。
修改后的完整代码
# 计算两个向量的Jaccard相似度 compare <- function(x1, x2) { x3 <- x1 + x2 ints <- sum(x3 > 1) uno <- sum(x3 > 0) return(ints / uno) } # 生成Jaccard相似度矩阵 getJaccard <- function(data) { l <- nrow(data) # 行数对应卡片数量 jmatrix <- matrix(nrow = l, ncol = l) for (i in 1:l) { for (j in i:l) { s <- compare(data[i, ], data[j, ]) # 对比两张卡片的分组数据 jmatrix[i, j] <- s jmatrix[j, i] <- s } } rownames(jmatrix) <- rownames(data) colnames(jmatrix) <- rownames(data) return(jmatrix) } # 卡片分类聚类主函数 cardsort <- function(file = "~/Downloads/cardsort_data2.csv", blocks, label_col = 1) { # 读取数据,将指定列设为行名(卡片编号) filedata <- read.table(file = file, header = TRUE, sep = ",", row.names = label_col) # 强制转换所有数据列为数值型 filedata <- as.data.frame(lapply(filedata, as.numeric)) # 生成Jaccard矩阵 jaccard_matrix <- getJaccard(filedata) # 聚类并绘图 hc <- hclust(dist(jaccard_matrix), method = "ward.D") plot(hc, main = paste("卡片分类聚类树状图 |", Sys.time()), cex = 0.8) rect.hclust(hc, k = blocks, border = "red") } # 调用函数(假设卡片编号在第1列) cardsort("~/Downloads/cardsort_data2.csv", 6)
关键修改点说明
数据读取与预处理
- 使用
row.names = label_col将卡片编号列设为数据框行名,剥离出纯数值的分类数据。 - 用
as.numeric强制转换所有数据列,彻底避免非数值干扰。
- 使用
Jaccard矩阵逻辑修正
- 调整维度计算为
nrow(data),以行对应单张卡片,计算卡片间的相似度。 - 给Jaccard矩阵添加行/列名(卡片编号),确保聚类时标签传递正确。
- 调整维度计算为
聚类绘图优化
- 直接基于Jaccard矩阵计算距离,无需额外转置。
- 优化标题说明,用
cex = 0.8调整标签大小避免重叠。
适配其他数据结构
如果你的CSV是列代表卡片,行代表参与者,只需调整以下部分:
getJaccard <- function(data) { l <- ncol(data) # 列数对应卡片数量 jmatrix <- matrix(nrow = l, ncol = l) for (i in 1:l) { for (j in i:l) { s <- compare(data[, i], data[, j]) # 对比两列(卡片)的所有参与者分类 jmatrix[i, j] <- s jmatrix[j, i] <- s } } rownames(jmatrix) <- colnames(data) colnames(jmatrix) <- colnames(data) return(jmatrix) } # 聚类部分改为 hc <- hclust(dist(t(filedata)), method = "ward.D")
内容的提问来源于stack exchange,提问作者Weston Nils
相关产品推荐
相关产品推荐

