2

我有一个 data.frame,其中包含多个预测变量,每个类型因子和一个响应/结果列。我需要为每个预测变量生成一个整体度量,它是因子聚合级别的计算摘要。

我希望有人可以提供一个粗略的解决方案来解决这个计算问题,而无需像我过去那样使用循环。

到目前为止我尝试过的

以前我没有执行后续聚合,我依靠一些非常糟糕的 R 代码循环,为每一列生成一个商品和坏品的频率表,添加商品和坏品总数,计算出贡献,然后计算哎呀。这会导致每列有一个表,因此我必须再次循环以总结每个 WoE 并将其存储在一个表中。

从那以后,我开始使用 plyr 并且可以对数据进行基本的汇总和转换操作,但这似乎远远超出了基础。

计算

Weight of Evidence (WoE) = sum ( Factor-level WoEs )

其中每个因子水平 WoE 计算为log(goodContribution/badContribution) ,贡献定义为Number of [goods] for factor / total number of [goods]

单列分步计算示例

example<-data.frame(colA=factor(rep(letters[1:3],4)),
                    colB=factor(rep(letters[4:6],4)),
                    colC=factor(rep(letters[8:10],4)))

outcome<-factor(rep(c(1,0),6),labels=c("bad","good"))

wip <- as.data.frame(xtabs(formula = ~example$colA +  outcome))
wip <- dcast(wip, example.colA ~ outcome)
wip$badTotal<-sum(wip$bad)
wip$goodTotal<-sum(wip$good)
wip$badContribution<-wip$bad/wip$badTotal
wip$goodContribution<-wip$good/wip$goodTotal
wip$WOE<-log(wip$goodContribution/wip$badContribution)

outputs<-data.frame(col=c("colA"),WoE=sum(wip$WOE))

更新

在示例中,WoE 计算结果为 0。在现实生活中,计算更加复杂,因为如果它等于 0,则将一个小数 (0.0001) 添加到好或坏的总数中,这样我们就不会将 0 或 Inf 传递给日志。

我已经包含了一个计算步骤并将结果添加到输出中。以前,我会遍历所有列并将结果添加到输出表以获取所有 WoE。为简单起见,我不希望循环结构干扰我之前编写的用于计算 WoE 的核心代码。

4

1 回答 1

2

这是一种使用data.table. 请注意,我习惯keyby按 排序结果outcome,这让我以后有些头疼。另请注意,您的输入数据具有导致WOE所有条目为零的不幸属性。

library(data.table)
dt = data.table(example)

totals = dt[, .N, keyby = outcome]
#   outcome N
#1:     bad 6
#2:    good 6

result = dt[, .N, keyby = list(colB, outcome)][,
              setNames(as.list(N/totals[,N]), totals[, outcome]), by = colB][,
              WOE := log(good/bad)]
result
#   colB       bad      good WOE
#1:    d 0.3333333 0.3333333   0
#2:    e 0.3333333 0.3333333   0
#3:    f 0.3333333 0.3333333   0

(由 OP 编辑​​)要使代码适用于所有行并返回结果的 data.frame,请使用lapply

#produce a list of results
result <- lapply(names(dt), function(colname){dt[,.N,keyby=c(colname,"outcome")][
  ,setNames(as.list(N/totals[,N]),totals[,outcome]),by=colname][
    ,WoE:=log(good/bad)][, list(colname,WoE=sum(WoE))]})

#collapse list into a data.table
rbindlist(result)
于 2013-07-29T17:38:14.810 回答