我正在尝试将符合条件的数据框中的所有列传递给dplyr的summarize函数中的一个函数,如下所示:
现在我想使用以下函数计算这些预测的多类LogLoss:
理想情况下,我希望不改变
谢谢!
注:mcll 的输入是一个真实值向量和一个概率矩阵,每一列都对应一个“pred”列。对于每个数据子集,mcll 应该返回一个标量。我可以使用下面的代码精确地得到我想要的结果,但我希望在 dplyr 的上下文中完成这件事。
df %>% group_by(Version, Type) %>%
summarize(mcll(TrueClass, starts_with("pred")))
Error: argument is of length zero
有没有方法可以实现这个?以下是一个可行的示例:
构建一个模拟数据框,包含样本预测。这些被解释为分类算法的输出。
library(dplyr)
nrow <- 40
ncol <- 4
set.seed(567879)
getProbs <- function(i) {
p <- runif(i)
return(p / sum(p))
}
df <- data.frame(matrix(NA, nrow, ncol))
for (i in seq(nrow)) df[i, ] <- getProbs(ncol)
names(df) <- paste0("pred.", seq(ncol))
添加一个列来表示真实类别
df$TrueClass <- factor(ceiling(runif(nrow, min = 0, max = ncol)))
增加分类列以进行子集分析
df$Type <- c(rep("a", nrow / 2), rep("b", nrow / 2))
df$Version <- rep(1:4, times = nrow / 4)
现在我想使用以下函数计算这些预测的多类LogLoss:
mcll <- function (act, pred)
{
if (class(act) != "factor") {
stop("act must be a factor")
}
pred[pred == 0] <- 1e-15
pred[pred == 1] <- 1 - 1e-15
dummies <- model.matrix(~act - 1)
if (nrow(dummies) != nrow(pred)) {
return(0)
}
return(-1 * (sum(dummies * log(pred)))/length(act))
}
这可以轻松地使用整个数据集完成。
act <- df$TrueClass
pred <- df %>% select(starts_with("pred"))
mcll(act, pred)
但我希望使用dplyr的group_by函数来计算数据子集的mcll值。
df %>% group_by(Version, Type) %>%
summarize(mcll(TrueClass, starts_with("pred")))
理想情况下,我希望不改变
mcll()
函数的前提下完成此操作,但如果这能简化其他代码,我也可以做出更改。谢谢!
注:mcll 的输入是一个真实值向量和一个概率矩阵,每一列都对应一个“pred”列。对于每个数据子集,mcll 应该返回一个标量。我可以使用下面的代码精确地得到我想要的结果,但我希望在 dplyr 的上下文中完成这件事。
mcll_df <- data.frame(matrix(ncol = 3, nrow = 8))
names(mcll_df) <- c("Type", "Version", "mcll")
count = 1
for (ver in unique(df$Version)) {
for (type in unique(df$Type)) {
subdat <- df %>% filter(Type == type & Version == ver)
val <- mcll(subdat$TrueClass, subdat %>% select(starts_with("pred")))
mcll_df[count, ] <- c(Type = type, Version = ver, mcll = val)
count = count + 1
}
}
head(mcll_df)
Type Version mcll
1 a 1 1.42972507510096
2 b 1 1.97189000832723
3 a 2 1.97988830406062
4 b 2 1.21387875938737
5 a 3 1.30629638026735
6 b 3 1.48799237895462
mutate()
做类似这样的事情,但好像不可能。你需要在调用那些以starts_with
开头的函数时有适当的上下文环境,在summarize()
中我认为这是不可用的(至少在我查看时是这样)。 - MrFlickdf %>% group_by(Version, Type) %>% summarise_at(vars(starts_with("pred")), funs(mcll(TrueClass, .)))
应该可以完成它 (?) - lukeA