如何在集群内进行集群

问题描述 投票:4回答:2

我在地图上有一组点,每个点都有一个给定的参数值。我想要:

  1. 在空间上对它们进行聚类,并忽略任何少于10个点的聚类。我的df应该有一个列(Clust),每个点属于[DONE]
  2. 对每个群集中的参数值进行子群集;在我的df(subClust)中添加一列,用于按子集对每个点进行分类。

我不知道如何做第二部分,除了可能有循环。

图像显示了由簇聚类编码的空间分布点(左上)的集合,并在右上图中按参数值排序。底行显示具有> 10个点(左)的簇和每个簇的面,按参数值(右)排序。正是这些方面,我希望能够根据最小的簇距离(d = 1)通过子簇对颜色进行颜色编码。

任何指针/帮助赞赏。我的可重现代码如下。

enter image description here

# TESTING
library(tidyverse)
library(gridExtra)

# Create a random (X, Y, Value) dataset
set.seed(36)
x_ex <- round(rnorm(200,50,20))
y_ex <- round(runif(200,0,85))
values <- rexp(200, 0.2)
df_ex <- data.frame(ID=1:length(y_ex),x=x_ex,y=y_ex,Test_Param=values)

# Cluster data by (X,Y) location
d = 4
chc <- hclust(dist(df_ex[,2:3]), method="single")

# Distance with a d threshold - used d=40 at one time but that changes...
chc.d40 <- cutree(chc, h=d) 
# max(chc.d40)

# Join results 
xy_df <- data.frame(df_ex, Clust=chc.d40)

# Plot results
breaks = max(chc.d40)
xy_df_filt <- xy_df %>% dplyr::group_by(Clust) %>% dplyr::mutate(n=n()) %>% dplyr::filter(n>10)# %>% nrow

p1 <- ggplot() +
  geom_point(data=xy_df, aes(x=x, y=y, colour = Clust)) +
  scale_color_gradientn(colours = rainbow(breaks)) +
  xlim(0,100) + ylim(0,100) 

p2 <- xy_df %>% dplyr::arrange(Test_Param) %>%
ggplot() +
  geom_point(aes(x=1:length(Test_Param),y=Test_Param, colour = Test_Param)) +
  scale_colour_gradient(low="red", high="green")

p3 <- ggplot() +
  geom_point(data=xy_df_filt, aes(x=x, y=y, colour = Clust)) +
  scale_color_gradientn(colours = rainbow(breaks)) +
  xlim(0,100) + ylim(0,100) 

p4 <- xy_df_filt %>% dplyr::arrange(Test_Param) %>%
ggplot() +
  geom_point(aes(x=1:length(Test_Param),y=Test_Param, colour = Test_Param)) +
  scale_colour_gradient(low="red", high="green") +
  facet_wrap(~Clust, scales="free")

grid.arrange(p1, p2, p3, p4, ncol=2, nrow=2)

THIS SNIPPET DOES NOT WORK - can't pipe within dplyr mutate() ...

# Second Hierarchical Clustering: Try to sub-cluster by Test_Param within the individual clusters I've already defined above
xy_df_filt %>% # This part does not work
  dplyr::group_by(Clust) %>% 
  dplyr::mutate(subClust = hclust(dist(.$Test_Param), method="single") %>% 
                  cutree(, h=1))

下面是一个使用循环的方法 - 但我真的更愿意学习如何使用dplyr或其他非循环方法。下面是一个显示子聚类方面的更新图像。

sub_df <- data.frame()
for (i in unique(xy_df_filt$Clust)) {
  temp_df <- xy_df_filt %>% dplyr::filter(Clust == i)
  # Cluster data by (X,Y) location
  a_d = 1
  a_chc <- hclust(dist(temp_df$Test_Param), method="single")

  # Distance with a d threshold - used d=40 at one time but that changes... 
  a_chc.d40 <- cutree(a_chc, h=a_d) 
  # max(chc.d40)

  # Join results to main df
  sub_df <- bind_rows(sub_df, data.frame(temp_df, subClust=a_chc.d40)) %>% dplyr::select(ID, subClust)
}
xy_df_filt_2 <- left_join(xy_df_filt,sub_df, by=c("ID"="ID"))

p4 <- xy_df_filt_2 %>% dplyr::arrange(Test_Param) %>%
ggplot() +
  geom_point(aes(x=1:length(Test_Param),y=Test_Param, colour = subClust)) +
  scale_colour_gradient(low="red", high="green") +
  facet_wrap(~Clust, scales="free")

grid.arrange(p1, p2, p3, p4, ncol=2, nrow=2)

enter image description here

r dplyr cluster-analysis apply hierarchical-clustering
2个回答
1
投票

应该有一种方法来使用dotidy的组合,但我总是很难按照我想要的方式使用do。相反,我通常做的是结合来自基地R的split和来自map_dfrpurrrsplit将通过Clust拆分数据框,并为您提供可以映射的数据框列表。 map_dfr映射每个数据帧并返回单个数据帧。

我从你的xy_df_filt开始,并产生了我认为应该与你从for循环得到的xy_df_filt_2相同的东西。我做了两个情节,虽然这两组很难看。

xy_df_filt_2 <- xy_df_filt %>%
    split(.$Clust) %>%
    map_dfr(function(df) {
        subClust <- hclust(dist(df$Test_Param), method = "single") %>% cutree(., h = 1)

        bind_cols(df, subClust = subClust)
    })

ggplot(xy_df_filt_2, aes(x = x, y = y, color = as.factor(subClust), shape = as.factor(Clust))) +
    geom_point() +
    scale_color_brewer(palette = "Set2")

更清晰的切面

ggplot(xy_df_filt_2, aes(x = x, y = y, color = as.factor(subClust), shape = as.factor(Clust))) +
    geom_point() +
    scale_color_brewer(palette = "Set2") +
    facet_wrap(~ Clust)

reprex package创建于2018-04-14(v0.2.0)。


1
投票

您可以为您的子群集执行此操作...

xy_df_filt_2 <- xy_df_filt %>% 
                group_by(Clust) %>% 
                mutate(subClust = tibble(Test_Param) %>% 
                                  dist() %>% 
                                  hclust(method="single") %>% 
                                  cutree(h=1))

嵌套管道很好。我认为你的版本的问题是你没有将正确的对象传递给dist。如果你只将一个列传递给tibble,则不需要dist术语,但是如果你想要使用多个列来进行主聚类,我就把它留下了。

您可以使用相同类型的公式,但没有group_by,从xy_df计算df_ex

© www.soinside.com 2019 - 2024. All rights reserved.