gpt4 book ai didi

r - 如何将多列传递给 dplyr::summarize 中的函数

转载 作者:行者123 更新时间:2023-12-02 17:22:12 25 4
gpt4 key购买 nike

我试图将与条件匹配的 data.frame 中的所有列传递给 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

最佳答案

使用data.table可以轻松做到这一点:

library(data.table)

setDT(df)[, mcll(TrueClass, .SD), by = .(Version, Type), .SDcols = grep("^pred", names(df))]
# Version Type V1
#1: 1 a 1.429725
#2: 2 a 1.979888
#3: 3 a 1.306296
#4: 4 a 1.668330
#5: 1 b 1.971890
#6: 2 b 1.213879
#7: 3 b 1.487992
#8: 4 b 1.171286

关于r - 如何将多列传递给 dplyr::summarize 中的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40045453/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com