【问题标题】:relabel clusters (column) in descending order in data table in R在R中的数据表中按降序重新标记集群(列)
【发布时间】:2019-11-26 13:32:52
【问题描述】:

假设我有一个数据表

 data = data.table(city = c("NYC", "LA", "Hawaii", "Essex"),
                   population = c(10, 9, 1, 2)
                   )

我对它应用 k-means,得到质心和标签,经过操作后得到

data = data.table(city = c("NYC", "LA", "Hawaii", "Essex"),
              population = c(10, 9, 1, 2),
              cluster = c(1, 1, 2, 2),
              centroids = c(9.5, 1.5)
              )

我们在哪里

cluster_centroids <- c(9.5, 1.5) cluster_labels <- c(1, 2)

如何按降序重新标记簇列的标签,以便所需的结果如下所示:

data = data.table(city = c("NYC", "LA", "Hawaii", "Essex"),
              population = c(10, 9, 1, 2),
              cluster = c(2, 2, 1, 1),
              centroids = c(9.5, 1.5)
              )

我想根据质心的值对它们进行排序。 我希望标签与质心一起使用,人口越高,标签就越高。 (对于有k 集群并且cluster 列值中没有顺序的一般情况,请考虑这一点。例如,原始集群列的顺序可能像1 是人口最多的城市,k是第二个人口稠密的城市,等等)

我不想对数据表的行进行排序。我想将 NYC 的标签从 1 更改为 2,将夏威夷的标签从 2 更改为 1。像 (1, 2) 映射到 (2, 1) 以便人口最多的城市被标记为最大标签,并且人口最少的城市标有 1

实际问题中的簇数不是 2。我只是想保持简单。

【问题讨论】:

  • 我想你在找setorder()

标签: r sorting data.table mapping


【解决方案1】:

[更新]以反映对原始帖子的澄清:

dt <- data.table(city = c("NYC", "LA", "Hawaii", "Essex"),
                 population = c(10, 9, 1, 2),
                 cluster = c(1, 1, 2, 2)
) %>% group_by(cluster) %>% #create the centroids variable
  mutate(centroid = mean(population)) %>% ungroup()

# implicitly rank the centroids, assigning increasing integers to decreasing vals
#assign the result as the cluster
dt %>% mutate("cluster" = frankv(centroid, ties.method = "dense"))

# A tibble: 4 x 4
  city   population cluster centroid
  <chr>       <dbl>   <int>    <dbl>
1 NYC            10       2      9.5
2 LA              9       2      9.5
3 Hawaii          1       1      1.5
4 Essex           2       1      1.5

[上一个]

您可以使用以下公式对任何变量进行反向编码:max(x)+min(x) - x

dt <- data.table(city = c("NYC", "LA", "Hawaii", "Essex"),
                 population = c(10, 9, 1, 2),
                 cluster = c(1, 1, 2, 2)
) 

dt %>% mutate_at("cluster", ~max(.)+1-.)

    city population cluster
1    NYC         10       2
2     LA          9       2
3 Hawaii          1       1
4  Essex          2       1

另一个解决方案是使用case_when,如果您有超过 2 个类别,并且您不想“反向编码”它们本身:

dt %>% mutate("cluster" = case_when(cluster == 2 ~ 1, cluster == 1 ~ 2))

    city population cluster
1    NYC         10       2
2     LA          9       2
3 Hawaii          1       1
4  Essex          2       1

【讨论】:

  • +1~max(.)+1-. 中的作用是什么?它必须是no_closters - 1?如果有 4 个集群,我们应该有 ~max(.)+3-.?
  • 如果你有 4 个簇,并且你想对它们进行反向编码,你希望 4 变成 1,以此类推。编码范围的最大值是 4. 4 + 1 = 5. 5 - 4 = 1。那么你想让 3 变成 2。 4 + 1 = 5. 5 - 3 = 2. 假设编码范围的最小值为 1。否则公式为max(x) + min(x) - x
  • 在我拥有的集群中,有 4 个集群,原始集群没有以递增的方式标记,它被搞砸了。比如 1 对应于最大人口,2 是最小人口,3 和 4 是其他东西。我想根据centroids 中的值对它们进行排序。所以,我并不是想让 1 映射到 4,也许需要将 1 映射到 3 或 2。这需要通过 centroids 自动检测,而不是以硬编码方式。
  • 这个问题并不清楚,IMO,我建议添加一个编辑,然后在你想要的输出中包含一个centroids 的列,以展示你的要求。
  • 当然。这不是我的简化第一次造成混乱!谢谢
【解决方案2】:

我想根据质心的值对它们进行排序

另一种方式:

# OP's input
clusterDT = data.table(old_label = 1:2, centroid = c(9.5, 1.5))

# overwrite labels by sorting and assigning row number
clusterDT[order(centroid), new_label := .I]

# update data
data[, cluster := clusterDT[.SD, on=.(old_label = cluster), x.new_label]]

     city population cluster
1:    NYC         10       2
2:     LA          9       2
3: Hawaii          1       1
4:  Essex          2       1

【讨论】:

  • 太棒了。感谢您的解决方案,以及简洁的提问方式!
猜你喜欢
  • 1970-01-01
  • 2021-09-26
  • 1970-01-01
  • 1970-01-01
  • 2018-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多