通过最大化 R 中增加虚拟变量(列)分组的普遍性来创建 CDF data.table

Creating a CDF by Maximizing Prevalence for Increasing Groupings of Dummy Variables (Columns) in R data.table

我有非排他性的患病率数据 categories/classifications。 (例如,一个故事可以是 'amazing'、'boring'、'charming'、'dark' 或这四者的任意组合。)说明性的:

library(data.table)

set.seed(0)
results = as.data.table( expand.grid( rep( list(0:1) , 4 ) ) )
names(results) = c('a', 'b', 'c', 'd')
results$prevalence = runif( n = 16 )
results$prevalence = results$prevalence/sum(results$prevalence)

我希望能够回答以下问题:

  1. (琐碎)不属于任何类别(a = b = c = d = 0)的人口覆盖率是多少?
  2. 覆盖人口百分比最大的类别是什么?
  3. 覆盖人口比例最大的两个类别是什么?
  4. ...等等...

实际上,我想创建一个准 CDF,其中:

That is:

results[ ( a == 0 & b == 0 & d == 0 ) & rowSums( results[ , -'prevalence' ] ) <= 1 , sum(prevalence) ]

That is:

results[ ( a == 0 & d == 0 ) & rowSums( results[ , -'prevalence' ] ) <= 2 , sum(prevalence) ]

That is:

results[ ( d == 0 ) & rowSums( results[ , -'prevalence' ] ) <= 3 , sum(prevalence) ]

在这个有限的示例中,我只是检查了所有可能的类别,以通过对允许的非零类别进行分组来找到最大的流行度(实际上,正如您从我的代码片段中看到的那样,我正在做相反的事情并通过分组找到流行度限制为零的类别)。

我怎样才能以 data.table 的方式做到这一点,这样我就不必通过我的真实汇总数据集中虚拟变量(列)的许多组合来强制执行?

我怀疑它可能涉及一些我没有想到的 .EACHIlapply 的巧妙使用。

试试这个:

#' @param dat 'data.frame' (or derivative), with only binary indicator columns
#' @param prev 'numeric', the prevalence indicator to be summed
#' @param n 'integer', number of categories for limiting coverage
#' @return numeric, with attribute "columns" indicating the selected combination of columns
func <- function(dat, prev, n) {
  stopifnot(ncol(dat) >= n)
  if (n == ncol(dat)) {
    out <- sum(prev) # ideally 1
    attr(out, "columns") <- colnames(dat)
  } else {
    com <- t(combn(ncol(dat), ncol(dat) - n))
    vec <- apply(com, 1, function(ind) {
      sum(prev[rowSums(sapply(subset(dat, select = ind), `>`, 0)) < 1])
    })
    out <- max(vec)
    attr(out, "columns") <- colnames(dat)[-com[which.max(vec),]]
  }
  out
}

进行中:

func(results[,1:4], results$prevalence, 0)
# [1] 0.1038405
# attr(,"columns")
# character(0)
func(results[,1:4], results$prevalence, 1)
# [1] 0.2090139
# attr(,"columns")
# [1] "c"
func(results[,1:4], results$prevalence, 2)
# [1] 0.3561435
# attr(,"columns")
# [1] "b" "c"
func(results[,1:4], results$prevalence, 3)
# [1] 0.5859805
# attr(,"columns")
# [1] "a" "b" "c"
func(results[,1:4], results$prevalence, 4)
# [1] 1
# attr(,"columns")
# [1] "a" "b" "c" "d"

这不是 data.table 语法,但它是兼容的:

results[, func(.SD, prevalence, 2), .SDcols = a:d]
# [1] 0.3561435
# attr(,"columns")
# [1] "b" "c"

或一次所有数字:

results[, sapply(c(0L, seq_along(.SD)), func, dat = .SD, prev = prevalence), .SDcols = a:d]
# [1] 0.1038405 0.2090139 0.3561435 0.5859805 1.0000000

将数据分成单独的“类别列”(dat) 和一个 prevalence 对象的目的是通过 combn 简化列选择并且不难-代码列名称、计数或函数中的位置。