面向层次聚类分析:大数据集按唯一个体计算坐标均值
解决方案:计算个体坐标均值并开展层次聚类
一、高效计算每个个体的坐标均值(不推荐for循环)
你的数据集是超百万行规模,for循环效率极低,推荐使用data.table(你的数据已为该格式)或dplyr的分组聚合方法,这两种都是向量化操作,处理大规模数据速度快很多。
方法1:使用data.table原生语法
# 按name和breed分组,计算lat和lng的均值 mean_coords <- dt[, .(mean_lat = mean(lat), mean_lng = mean(lng)), by = .(name, breed)]
方法2:使用dplyr(tidyverse风格)
如果习惯tidyverse工具链,可以用这个:
library(dplyr) mean_coords <- dt %>% group_by(name, breed) %>% summarise(mean_lat = mean(lat), mean_lng = mean(lng), .groups = "drop") # 取消分组状态
如果你坚持要用for循环(不推荐)
注意:百万行数据下这个方法会非常慢,因为每次rbind都会重新分配内存,仅作参考:
# 获取所有唯一个体name unique_names <- unique(dt$name) # 初始化结果数据框 mean_coords_for <- data.frame( name = character(), breed = character(), mean_lat = numeric(), mean_lng = numeric(), stringsAsFactors = FALSE ) # 循环每个个体 for(nm in unique_names) { # 筛选当前个体的数据 subset_dt <- dt[name == nm,] # 计算坐标均值 avg_lat <- mean(subset_dt$lat) avg_lng <- mean(subset_dt$lng) # 获取该个体所属组别(每个name对应唯一breed,取第一个值即可) breed_group <- subset_dt$breed[1] # 将结果追加到数据框 mean_coords_for <- rbind(mean_coords_for, data.frame(name = nm, breed = breed_group, mean_lat = avg_lat, mean_lng = avg_lng)) }
二、分组准备聚类数据
将均值数据按a、b组分开,方便后续组内聚类:
# 提取a组数据 group_a <- mean_coords[breed == "a"] # 提取b组数据 group_b <- mean_coords[breed == "b"]
三、组内层次聚类(注意地理坐标的距离计算)
普通欧氏距离不适合经纬度数据,推荐用geosphere包计算地理距离(比如哈弗辛距离),再进行层次聚类:
library(geosphere) # --- 处理a组 --- # 计算个体间的地理距离(注意传入顺序是lng, lat) dist_a <- distHaversine(group_a[, .(mean_lng, mean_lat)]) # 执行层次聚类,这里用ward.D2方法(适合最小化组内方差) hc_a <- hclust(dist_a, method = "ward.D2") # 绘制聚类树 plot(hc_a, labels = group_a$name, main = "A组个体层次聚类树") # --- 处理b组 --- dist_b <- distHaversine(group_b[, .(mean_lng, mean_lat)]) hc_b <- hclust(dist_b, method = "ward.D2") plot(hc_b, labels = group_b$name, main = "B组个体层次聚类树")
内容的提问来源于stack exchange,提问作者Jackijones
相关产品推荐
相关产品推荐

