如何基于邻域密度计算tSNE散点图点的着色分数?
解决tSNE散点图基于局部邻域密度着色的问题
嘿,我完全懂你想要的效果——让聚集在一起的点颜色更深,稀疏分散的点颜色更浅,核心就是要计算每个点的局部邻域密度得分,而你当前用的是全局距离总和,这肯定达不到预期,因为它衡量的是每个点到所有其他点的整体距离,和局部聚集度无关。
下面给你两种实用的局部密度计算方法,都是R里可以直接实现的:
方法1:基于K近邻的局部密度(推荐)
这种方法是给每个点找它的K个最近邻居,通过邻居的平均距离来衡量密度——邻居越近,密度越高;K值可以根据你的数据规模调整(比如10、20,试到合适为止)。
步骤如下:
- 先加载
FNN包(用来高效计算K近邻):
install.packages("FNN") library(FNN)
- 计算每个点的K近邻距离,并推导密度得分:
# 假设best.tsne是你的tSNE坐标矩阵 k <- 10 # 可以根据数据调整这个K值 # 获取每个点的K个最近邻居的距离 knn_distances <- get.knn(best.tsne, k = k)$nn.dist # 计算局部密度:用K近邻平均距离的倒数(距离越小,密度值越大) local_density <- 1 / rowMeans(knn_distances) # 如果你想更突出距离的影响,也可以用距离总和的倒数: # local_density <- 1 / rowSums(knn_distances)
- 把密度值缩放到0-1区间(方便配色):
# 用scales包的rescale函数,没有的话先安装install.packages("scales") scaled_density <- scales::rescale(local_density, to = c(0, 1))
方法2:基于固定半径的局部密度
这种方法是设定一个固定半径r,统计每个点在r范围内的邻居数量——数量越多,密度越高。r的取值可以参考K近邻的平均距离,或者根据你的数据分布调整。
步骤如下:
- 加载
dbscan包(用来快速计算半径内的邻居数):
install.packages("dbscan") library(dbscan)
- 计算半径r并统计邻域内的点数:
# 先通过K近邻确定一个合适的r,比如用K=10的平均距离 k <- 10 r <- mean(rowMeans(get.knn(best.tsne, k = k)$nn.dist)) # 统计每个点在半径r内的邻居数(包括自身) local_density <- rowSums(dbscan::kNNdist(best.tsne, k = nrow(best.tsne)) <= r) # 同样缩放到0-1区间 scaled_density <- scales::rescale(local_density, to = c(0, 1))
最后完成着色和绘图
拿到scaled_density之后,就可以用你熟悉的方式分配颜色了:
ii <- cut(scaled_density, breaks = seq(min(scaled_density), max(scaled_density), len = 100), include.lowest = TRUE) colors <- colorRampPalette(c("white", "blue"))(99)[ii] # 绘制tSNE散点图 plot(best.tsne, col = colors, pch = 16, main = "tSNE with Local Density Coloring")
这样出来的图就会和你的mockup一致:聚集的点因为局部密度高,颜色更深;稀疏的点密度低,颜色更浅。你可以多调整K值或者r值,找到最贴合你数据的可视化效果~
内容的提问来源于stack exchange,提问作者Yuriy Grabovsky
相关产品推荐
相关产品推荐

