【问题标题】:Cluster observations based on multiple variables基于多个变量的聚类观察
【发布时间】:2019-12-09 22:46:37
【问题描述】:

我正在寻找一个 r 函数来基于两个变量在我的数据集中创建集群(希望“集群”是我想做的正确名称)。变量_1 或变量_2 具有相同值的每两个观察值应该在同一个集群中。在下面的简短示例中,我根据 variable_1 和 variable_2 聚合数据帧 df。

df <- data.frame(variable_1=c("a","a","b","b","c","c","d","d","e","e"),variable_2=c("g1","g2","g1","g3","g2","g4","g4","g6","g7","g8"),value=rnorm(10))

df$clusters <- some_function_to_create_clusters(df[,c("variable_1","variable_2")])

结果应该是这样的:

df$clusters <- c("clu1","clu1","clu1","clu1","clu1","clu1","clu1","clu1","clu2","clu2")
df

请注意,第一个集群包含 variable_1 等于“a”、“b”、“c”或“d”的所有人:“a”和“b”合并在一起,因为它们共享“g1”(第 1 行和第 1 行) 3); “a”和“c”被合并,因为它们共享“g2”(第 2 行和第 5 行);和 "c" 和 "d" 被合并,因为它们共享 "g4"(第 6 行和第 7 行)。 最后,在最后一个集群中,只有 variable_1=="e" 的观察值,因为它们不与任何人共享 variable_2。

为了澄清我打算做什么,我会更好地解释我的问题集。我正在将县与附近的旅游景点配对。不同的县周围有不同的旅游景点(TA),同一个县周围有很多旅游景点。但是,这个县和 TA 的“旅游集群”在该国很少分布。请注意,由于县与旅游景点连接的“连锁”效应,一些遥远的县可能在同一个集群内。所以我想根据县和旅游景点的 id 找到那些“集群”。

这看起来很简单,但我不知道如何实现。

非常感谢

【问题讨论】:

标签: r aggregate cluster-computing


【解决方案1】:

igraph 解决方案

免责声明:我对 igraph 完全陌生,因此可能有更好的解决方案来解决这个问题。不过这似乎可行。

使用igraph 包,我们可以使用graph_from_data_frame() 函数对数据进行聚类,然后使用components 提取聚类。您可以获得能够可视化集群的额外优势。

library(igraph)

graph <- graph_from_data_frame(df[, 1:2], directed = FALSE)

cmp <- components(graph)$membership

df$cluster <- cmp[df$variable_1]

plot(graph)

将其包装成一个函数

如果你想把它包装成一个函数,这样的工作:

find_clusters <- function(x, y) {
  edges <- data.frame(from = x, to = y)
  graph <- igraph::graph_from_data_frame(edges, directed = FALSE)
  cmp <- igraph::components(graph)$membership
  return(cmp[x])
}

使用您在上面作为评论发布的其他示例,我们因此具有以下工作流程:

library(dplyr)

df <- data.frame(
    variable_1 = c("a", "a", "b", "b", "c", "c", "d", "d", "e", "e", "f", "f"),
    variable_2 = c( "g1", "g2", "g1", "g3", "g2", "g4", "g4", "g6", "g7", "g8", "g9", "g12"),
    value = rnorm(12)
  )

df %>% 
  mutate(cluster = find_clusters(variable_1, variable_2))

#    variable_1 variable_2       value  cluster
# 1           a         g1 -0.03410073        1
# 2           a         g2  0.51261548        1
# 3           b         g1  0.06470451        1
# 4           b         g3 -1.97228101        1
# 5           c         g2 -0.39751063        1
# 6           c         g4  0.17761619        1
# 7           d         g4 -0.13771207        1
# 8           d         g6 -0.72183017        1
# 9           e         g7  0.09012701        2
# 10          e         g8  0.45763593        2
# 11          f         g9 -0.83172613        3
# 12          f        g12  2.83480352        3

【讨论】:

    【解决方案2】:

    所以,我写了一个函数来实现我所需要的。它很丑陋,但它正在工作。如果有人有更好/更有效的解决方案,我将不胜感激。

    find_clusters <- function(original_df){
    
      find_clus <- original_df
      cluster_number <- 1
      find_clus$cluster <- "cl"
      i=1
      for(i in 1:nrow(find_clus)){
        if(nchar(find_clus$cluster[i])>2) next
        aux <- lapply(original_df,function(x){ which(x==x[i])})%>% reshape2::melt()
        idx <- aux$value %>%unique() %>%sort()
        j = 1
        while(j <= length(idx)){
          aux <- lapply(original_df,function(x){ which(x==x[idx[j]])})%>% reshape2::melt()
          idx <- c( idx, aux$value) %>%unique() %>% sort()
          j <- j+1
        }
    
    
        find_clus$cluster[idx] <- paste0("cl",sprintf("%04d",  cluster_number))
        cluster_number<- cluster_number +1
      }  
      return(find_clus$cluster)
    }
    

    所以,要找到集群,应该这样写:

    find_clusters(df[,c(1,2)])
    

    【讨论】:

      猜你喜欢
      • 2015-08-12
      • 1970-01-01
      • 2022-06-17
      • 2019-01-05
      • 2016-02-07
      • 1970-01-01
      • 2013-12-03
      • 2014-10-10
      • 1970-01-01
      相关资源
      最近更新 更多