我有一个data.frame,其中包含各种类型因子和响应/结果列的预测变量。我需要为每个预测变量生成一个总体度量,它是一个因子汇总级别的计算摘要。
我希望有人可以提供一个粗略的解决方案来解决这个计算问题,而不像我过去那样诉诸循环。
到目前为止我尝试了什么
以前我没有进行过后续的聚合,我依靠一些非常糟糕的R代码,我循环遍历,为每列产生商品和坏的频率表,添加商品和货物。糟糕的总计,计算出贡献,然后计算WoE。这导致每列一个表,所以我必须再次循环以总结每个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的核心代码。
答案 0 :(得分: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)