You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言优化:非0簇标签频次统计及占比计算函数的高效实现

问题需求

我有聚类算法输出的簇编号向量cluster(取值0到n),以及标签值为0和1的向量label,需要完成以下操作:

  • 排除簇0,统计其余每个簇中标签0和1的出现次数
  • 计算每个簇中标签1的占比
  • 按标签1的占比降序排序结果

我自己写了cluster_metrics函数实现功能,但觉得不符合R语言的惯用风格,想找更高效的实现方式。


测试数据

聚类结果向量

set.seed(1)
cluster <- sample(0:5, 100, replace = T)
cluster
  [1] 0 3 0 1 4 2 5 1 2 2 0 4 4 1 5 5 1 0 4 4 0 0 5 4 4 1 1 5 0 3 0 3 2 5 1 1 5 3 3
 [40] 3 1 3 0 5 0 3 0 5 1 2 1 5 5 1 4 1 5 5 5 0 2 2 5 3 5 2 0 3 4 0 0 5 3 4 4 3 5 4
 [79] 3 3 0 4 4 5 0 0 2 5 1 1 2 5 1 3 2 4 1 1 0 2

标签向量

label <- sample(0:1, 100, replace = T)
label
  [1] 0 1 0 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 0 1 0 0 0 0 1 1 1 1 1 0 0 0 1 0 0 1 0 0 1
 [40] 0 0 1 0 0 1 1 1 1 0 1 0 0 0 0 0 1 0 1 0 0 1 0 1 1 1 0 1 0 0 1 1 0 1 1 1 0 0 1
 [79] 0 0 0 0 1 0 0 0 1 1 0 1 1 1 1 1 0 1 0 0 1 0

期望输出

cluster_metrics(cluster,label)
     clust sum_1 sum_0   percent
[1,]     2     7     5 0.5833333
[2,]     4     8     7 0.5333333
[3,]     1     9     9 0.5000000
[4,]     5    10    11 0.4761905
[5,]     3     7     8 0.4666667

现有实现函数

cluster_metrics <- function(clust, label){
  mx <-  max(clust)
  res <- matrix(NA,ncol=4,nrow=mx)
  colnames(res) <- c("clust","sum_1","sum_0","percent")
  for(i in 1:mx){
    id <- clust==i
    s1 <- sum(label[id]==1)
    s0 <- sum(label[id]==0)
    res[i,] <- c(i, s1, s0, s1/(s1+s0))
  }
  res[order(res[,"percent"],decreasing = T),]
}

性能测试结果

Unit: microseconds
                              expr       min        lq       mean     median         uq       max
             my_fu(cluster, label)   185.305   229.208   254.8142   251.1595   275.3915   382.584
           PGSA_fu(cluster, label)   909.419  1003.496  1272.7706  1133.7810  1287.4410 10025.276
         jay.sf_fu(cluster, label)  6152.120  6437.774  7196.9997  6787.0025  7515.1085 16177.966
 ThomasIsCoding_fu(cluster, label)  1167.705  1286.871  1438.5756  1385.2250  1488.1410  3471.757
  Jilber_Urbina_fu(cluster, label) 17980.839 19044.489 21186.8975 19953.9080 21575.1820 51005.578
 neval
   100
   100
   100
   100
   100

更符合R风格的高效实现

方案1:Base R(无额外依赖)

利用向量化操作替代循环,更贴合R语言惯用逻辑:

cluster_metrics_base <- function(clust, label) {
  # 过滤簇0并整理数据
  df <- data.frame(clust = clust, label = label) |>
    subset(clust != 0)
  
  # 交叉统计各簇标签分布
  tab <- table(df$clust, df$label)
  # 转换为结果数据框并计算占比
  res <- data.frame(
    clust = as.integer(rownames(tab)),
    sum_1 = tab[, "1"],
    sum_0 = tab[, "0"],
    percent = tab[, "1"] / rowSums(tab)
  )
  
  # 降序排序并重置行名
  res <- res[order(-res$percent), ]
  rownames(res) <- NULL
  res
}

方案2:dplyr(简洁易读)

借助tidyverse工具链,代码可读性更强:

library(dplyr)
library(tidyr)

cluster_metrics_dplyr <- function(clust, label) {
  tibble(clust = clust, label = label) |>
    filter(clust != 0) |>
    count(clust, label) |>
    pivot_wider(names_from = label, values_from = n, names_prefix = "sum_", values_fill = 0) |>
    mutate(percent = sum_1 / (sum_1 + sum_0)) |>
    arrange(desc(percent))
}

方案3:data.table(大数据场景最优)

适合处理超大规模数据集,性能优势明显:

library(data.table)

cluster_metrics_dt <- function(clust, label) {
  dt <- data.table(clust = clust, label = label)[clust != 0]
  dt[, .(sum_1 = sum(label == 1), sum_0 = sum(label == 0)), by = clust][
    , percent := sum_1 / (sum_1 + sum_0)][
      order(-percent)]
}

内容的提问来源于stack exchange,提问作者mr.T

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 15:25:57