r - 用户定义的 R 函数没有用 dplyr 给出正确的答案
问题描述
我正在尝试执行与此处的示例完全相同的分析,但使用不同的 beta 分布参数化。在分析开始时,我不确定我想要什么参数化,所以我定义了一个自定义函数,以便我可以在一个地方进行参数化更改,然后在其余代码中使用。见下文。
f_beta <- function(x, elig, par) {
return (
dbeta(x,
exp(par[1] + par[2] * log(elig)),
exp(par[3] + par[4] * log(elig)),
log = TRUE))
}
当我尝试将该函数应用于数据帧的数据时,它不会返回正确的结果。"likelihood" 和 "likelihood2" 字段应该返回相同的结果,但事实并非如此。
assignments <- df %>%
select(-cluster) %>%
crossing(fits) %>%
mutate(likelihood = prior * dbeta(enrpct, exp(a0 + b0 * log(elig)), exp(a1 + b1 * log(elig)), log = TRUE),
likelihood2 = prior * f_beta(enrpct, elig, c(a0, b0, a1, b1))) %>%
group_by(id) %>%
top_n(1, likelihood) %>%
ungroup()
完整代码如下。
library(tidyr)
library(dplyr)
# custom beta distribution parameterization
f_beta <- function(x, elig, par) {
return (dbeta(x, exp(par[1] + par[2] * log(elig)), exp(par[3] + par[4] * log(elig)), log = TRUE))
}
# log-likelihood
ll <- function(x, elig, par) {
-sum(f_beta(x, elig, par))
}
# optimizer
fit_beta <- function(x, elig, init = c(-0.5, 0.2, -1.1, 0.3)) {
m <- optim(par = init, fn = ll, elig = elig, x = x)
coef <- m$par
data_frame(a0 = coef[1], b0 = coef[2], a1 = coef[3], b1 = coef[4], number = length(x))
}
####### generate data
n <- 10000
n2 <- 5000
# mixture 1 parameters
a0 <- -1
b0 <- 0.3
a1 <- -2
b1 <- 1
# mixture 2 parameters
a01 <- -1
b01 <- 0.5
a11 <- -1.5
b11 <- 0.8
# generate data
df <- data.frame(id = 1:n, elig = sample(1:100, size = n, replace = TRUE) * 100)
df$enrpct <- rbeta(n, exp(a0 + b0 * log(df$elig)), exp(a1 + b1 * log(df$elig)))
df2 <- data.frame(id = (n+1):(n+n2), elig = sample(1:100, size = n2, replace = TRUE) * 100)
df2$enrpct <- rbeta(n2, exp(a01 + b01 * log(df2$elig)), exp(a11 + b11 * log(df2$elig)))
df <- rbind(df, df2)
# assign to clusters randomly like in example
df$cluster <- factor(sample(c("A", "B"), nrow(df), replace = TRUE))
# maximization step of E-M algorithm
fits <- df %>%
group_by(cluster) %>%
do(fit_beta(.$enrpct, .$elig)) %>%
ungroup() %>%
mutate(prior = number / sum(number))
# expectation step of E-M algorithm
assignments <- df %>%
select(-cluster) %>%
crossing(fits) %>%
mutate(likelihood = prior * dbeta(enrpct, exp(a0 + b0 * log(elig)), exp(a1 + b1 * log(elig)), log = TRUE),
likelihood2 = prior * f_beta(enrpct, elig, c(a0, b0, a1, b1))) %>%
group_by(id) %>%
top_n(1, likelihood) %>%
ungroup()
head(assignments)
解决方案
这是因为您c(a0, b0, a1, b1)
在计算时使用likelihood2
. 但是这些变量中的每一个都是数据框中的一整列,因此 usingc()
只会将它们连接起来,您最终将使用错误的值。
有了这个,它将起作用:
f_beta <- function(x, elig, a0, b0, a1, b1) {
return (dbeta(x, exp(a0 + b0 * log(elig)), exp(a1 + b1 * log(elig)), log = TRUE))
}
likelihood2 = prior * f_beta(enrpct, elig, a0, b0, a1, b1)
推荐阅读
- freebsd - FreeBSD OS 中“写”函数的定义在哪里
- json - 捆绑安装 Json 错误
- python-3.x - seaborn中分组箱线图的个别颜色
- apache-kafka - Clickhouse:选择时拆分输出
- sqlite - 运行时错误:查询时内存地址无效或无指针取消引用
- r - ggplot2图例:如何组合线型和形状
- python - 根据使用自动化脚本标记为删除的行删除 POLINE
- android - 如何从Android应用程序的Firebase中的实时数据库中删除数据(json的特定节点)
- sql - 如何在 SQL Server 中识别两列完全匹配的行
- wpf - WPF 使用 Canvas 作为 ImageSource