代码之家  ›  专栏  ›  技术社区  ›  Alexander

分组数据中的kmeans聚类

  •  6
  • Alexander  · 技术社区  · 6 年前

    目前,我试图在分组数据中找到集群中心。通过使用示例数据集和问题定义,我能够创建 kmeans 使用每组群集。然而,当涉及到为给定组寻址集群的每个中心时,我不知道如何获取它们。 https://rdrr.io/cran/broom/man/kmeans_tidiers.html

    采集样本数据 from (添加时几乎没有修改 gr (列) 示例数据

    library(dplyr)
    library(broom)
    library(ggplot2)
    
    set.seed(2015)
    
    sizes_1 <- c(20, 100, 500)
    sizes_2 <- c(10, 50, 100)
    
    centers_1 <- data_frame(x = c(1, 4, 6), 
                            y = c(5, 0, 6), 
                            n = sizes_1,
                            cluster = factor(1:3))
    centers_2 <- data_frame(x = c(1, 4, 6), 
                            y = c(5, 0, 6), 
                            n = sizes_2,
                            cluster = factor(1:3))
    
    points1 <- centers_1 %>% 
        group_by(cluster) %>%
        do(data_frame(x = rnorm(.$n, .$x), 
                      y = rnorm(.$n, .$y), 
                      gr="1"))
    
    points2 <- centers_2 %>% 
        group_by(cluster) %>%
        do(data_frame(x = rnorm(.$n, .$x), 
                      y = rnorm(.$n, .$y), 
                      gr="2"))
    
    combined_points <- rbind(points1, points2)
    
    > combined_points
    # A tibble: 780 x 4
    # Groups:   cluster [3]
       cluster           x        y    gr
        <fctr>       <dbl>    <dbl> <chr>
     1       1  3.66473833 4.285771     1
     2       1  0.51540619 5.565826     1
     3       1  0.11556319 5.592178     1
     4       1  1.60513712 5.360013     1
     5       1  2.18001557 4.955883     1
     6       1  1.53998887 4.530316     1
     7       1 -1.44165622 4.561338     1
     8       1  2.35076259 5.408538     1
     9       1 -0.03060973 4.980363     1
    10       1  2.22165205 5.125556     1
    # ... with 770 more rows
    
    ggplot(combined_points, aes(x, y)) +
        facet_wrap(~gr) +
        geom_point(aes(color = cluster))
    

    enter image description here

    好的,在这里之前一切都很好。当我要提取每个组中的每个群集中心时

    clust <- combined_points %>% 
        group_by(gr) %>% 
        dplyr::select(x, y) %>% 
        kmeans(3)
    
    > clust
    K-means clustering with 3 clusters of sizes 594, 150, 36
    
    Cluster means:
            gr        x         y
    1 1.166667 6.080832 6.0074885
    2 1.333333 4.055645 0.0654158
    3 1.305556 1.507862 5.2417670
    

    正如我们所看到的 gr公司 号码改变了,我不知道这些中心属于哪一组。

    我们向前走一步 tidy 格式为 clust

    > tidy(clust)
            x1       x2        x3 size  withinss cluster
    1 1.166667 6.080832 6.0074885  594 1095.3047       1
    2 1.333333 4.055645 0.0654158  150  312.4182       2
    3 1.305556 1.507862 5.2417670   36  115.2484       3
    

    我还是看不见 gr 2 中心信息。

    我希望问题解释得很清楚。如果您有任何缺少的部分,请告诉我!提前感谢!

    1 回复  |  直到 6 年前
        1
  •  6
  •   alistaire    6 年前

    kmeans 不理解dplyr分组,所以它只是找到三个整体中心,而不是在每个组内。此时,最好的习惯用法是列出输入数据的列,例如:。

    library(tidyverse)
    
    points_and_models <- combined_points %>% 
        ungroup() %>% select(-cluster) %>%    # cleanup, remove cluster name so data will collapse
        nest(x, y) %>%     # collapse input data into list column
        mutate(model = map(data, kmeans, 3),    # iterate model over list column of input data
               centers = map(model, broom::tidy))    # extract data from models
    
    points_and_models
    #> # A tibble: 2 x 4
    #>   gr    data               model        centers             
    #>   <chr> <list>             <list>       <list>              
    #> 1 1     <tibble [620 × 2]> <S3: kmeans> <data.frame [3 × 5]>
    #> 2 2     <tibble [160 × 2]> <S3: kmeans> <data.frame [3 × 5]>
    
    points_and_models %>% unnest(centers)
    #> # A tibble: 6 x 6
    #>   gr       x1     x2  size withinss cluster
    #>   <chr> <dbl>  <dbl> <int>    <dbl> <fct>  
    #> 1 1      4.29  5.71    158    441.  1      
    #> 2 1      3.79  0.121   102    213.  2      
    #> 3 1      6.39  6.06    360    534.  3      
    #> 4 2      5.94  5.88    100    194.  1      
    #> 5 2      4.01 -0.127    50     97.4 2      
    #> 6 2      1.07  4.57     10     15.7 3
    

    请注意 cluster 列来自模型结果,而不是输入数据。

    您也可以对 do ,例如。

    combined_points %>% 
        group_by(gr) %>% 
        do(model = kmeans(.[c('x', 'y')], 3)) %>% 
        ungroup() %>% group_by(gr) %>% 
        do(map_df(.$model, broom::tidy)) %>% ungroup()
    

    但是 在这一点上,分组rowwise有点不受欢迎,代码变得有点僵硬,您可以从需要显式 ungroup 太多了。