R 将速率摘要行优雅地转换为长二进制响应行?
背景:我正在运行一个小的a/B测试,使用2x2因子(前景的黑色和背景的白色,淡色和正常色),以及4个条件中每个条件的点击数和它们“转换”的速率(一个二进制变量,我定义为在页面上花费至少40秒)。进行一点编辑并进入一个漂亮的R数据帧非常容易:R 将速率摘要行优雅地转换为长二进制响应行?,r,glm,logistic-regression,R,Glm,Logistic Regression,背景:我正在运行一个小的a/B测试,使用2x2因子(前景的黑色和背景的白色,淡色和正常色),以及4个条件中每个条件的点击数和它们“转换”的速率(一个二进制变量,我定义为在页面上花费至少40秒)。进行一点编辑并进入一个漂亮的R数据帧非常容易: rates <- read.csv(stdin(),header=TRUE) Black,White,N,Rate TRUE,FALSE,512,0.2344 FALSE,TRUE,529,0.2098 TRUE,TRUE,495,0.1919 FAL
rates <- read.csv(stdin(),header=TRUE)
Black,White,N,Rate
TRUE,FALSE,512,0.2344
FALSE,TRUE,529,0.2098
TRUE,TRUE,495,0.1919
FALSE,FALSE,510,0.1882
ground <- NULL
for (i in 1:nrow(rates)) {
x <- rates[i,]
y <- do.call("rbind", replicate((x$N * x$Rate), data.frame(Black=c(x$Black),White=c(x$White),Conversion=c(TRUE)), simplify = FALSE))
z <- do.call("rbind", replicate((x$N * (1-x$Rate)), data.frame(Black=c(x$Black),White=c(x$White),Conversion=c(FALSE)), simplify = FALSE))
ground <- rbind(ground,y,z)
}
生成的数据帧地面
看起来正确:
sum(rates$N)
[1] 2046
nrow(ground)
[1] 2042
# the missing 4 are probably from the rounding-off of the reported conversion rate
summary(ground); head(ground, n=20)
Black White Conversion
Mode :logical Mode :logical Mode :logical
FALSE:1037 FALSE:1020 FALSE:1623
TRUE :1005 TRUE :1022 TRUE :419
NA's :0 NA's :0 NA's :0
Black White Conversion
1 TRUE FALSE TRUE
2 TRUE FALSE TRUE
3 TRUE FALSE TRUE
4 TRUE FALSE TRUE
5 TRUE FALSE TRUE
6 TRUE FALSE TRUE
7 TRUE FALSE TRUE
8 TRUE FALSE TRUE
9 TRUE FALSE TRUE
10 TRUE FALSE TRUE
11 TRUE FALSE TRUE
12 TRUE FALSE TRUE
13 TRUE FALSE TRUE
14 TRUE FALSE TRUE
15 TRUE FALSE TRUE
16 TRUE FALSE TRUE
17 TRUE FALSE TRUE
18 TRUE FALSE TRUE
19 TRUE FALSE TRUE
20 TRUE FALSE TRUE
同样,逻辑回归给出了一个理智的答案:
g <- glm(Conversion ~ Black*White, family=binomial, data=ground); summary(g)
...
Deviance Residuals:
Min 1Q Median 3Q Max
-0.732 -0.683 -0.650 -0.643 1.832
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -1.472 0.114 -12.94 <2e-16
BlackTRUE 0.291 0.154 1.88 0.060
WhiteTRUE 0.137 0.156 0.88 0.381
BlackTRUE:WhiteTRUE -0.404 0.220 -1.84 0.066
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 2072.7 on 2041 degrees of freedom
Residual deviance: 2068.2 on 2038 degrees of freedom
AIC: 2076
Number of Fisher Scoring iterations: 4
g | z |)
(截距)-1.472 0.114-12.94不太清楚要转换什么,但如果只需要为列n
中的每个值设置n
行,则
编辑——我很马虎。第一件事-根据需要将原始文件中的所有因子转换为数字或字符。那么
# just put in placeholder values
newdf<-data.frame(Black="n",White="n",Rate=0,stringsAsFactors=FALSE)
newdf[1:rates[1,3],]<-rates[1,c(1,2,4)]
newdf[4:rates[2,3],] <- rates[2,c(1,2,4)]
#只需输入占位符值即可
newdfrates$counts一件事是如何转换数据。另一个原因是。从?glm
:“[f]或二项式[…]家族[y]可将响应[…]指定为一个因子(当第一级表示失败和所有其他成功时),或指定为两列矩阵,其中列给出成功和失败的数量。”。第一种方式对应于“R的glm需要2046行的数据帧,每行报告一个真或假转换”。第二种方法基本上与原始数据集相对应,其中“成功率”可以很容易地从Rate和N计算出来。第三种方法是使用每个治疗组合的成功率作为反应变量,在这种情况下
试验次数必须作为权重
参数提供
set.seed(1)
# one row per observation
df1 <- data.frame(x = sample(c("yes", "no"), 40, replace = TRUE),
y = sample(c("yes", "no"), 40, replace = TRUE),
z = rbinom(n = 40, size = 1, prob = 0.5))
df1
library(plyr)
# aggregated data with one row per treatment combination
df2 <- ddply(.data = df1, .variables = .(x, y), summarize,
n = length(z),
rate = sum(z)/n,
success = n*rate,
failure = n - success)
df2
# three different ways to specify the models,
# which all give the same parameter estimates for x, y and x*y
mod1 <- glm(z ~ x * y, data = df1, family = binomial)
mod2 <- glm(cbind(success, failure) ~ x * y, data = df2, family = binomial)
mod3 <- glm(rate ~ x * y, data = df2, weights = n, family = binomial)
summary(mod1)
summary(mod2)
summary(mod3)
set.seed(1)
#每观察一行
df1glm
要求每个案例一行不是真的。有一种方法可以使用聚合数据。请参见?glm
。我明白了,所以它可以采用计数矩阵?但是我仍然需要转换为计数,如果不使用这里建议的一些技巧,我也不知道如何优雅地进行计数。我不明白你想做什么,但当我尝试时,它似乎不起作用。您对newdf
的定义对我来说是错误的(data.frame中的错误(黑、白、速率):未找到对象“Black”
),当我将其替换为data.frame(黑=”,白=”,速率=”)
然后运行newdf[1:rates[1,3],]…
它会产生一系列警告(警告消息:1:in'[权重是一种看起来很酷的方法,甚至比cbind
解决方案更简单,但我有点担心这些明显等效的方法没有得到相同的结果。在相同的回归中是相同的数据,不是吗?参数可能相同,但其他值不同。例如,复杂性度量:l看看mod1$aic;mod2$aic;mod3$aic
,你会看到长格式正在以一种非常不同的aic转变。@格温,对不起,我不明白你所说的“同一回归中的相同数据”是什么意思我介绍的三个模型的AIC值不能直接比较,因为它们有不同的响应变量,并且使用两个不同的数据集进行拟合。好吧,那么这就是一个问题:我不明白为什么3个表面上等效的方法使用“两个不同的数据集”。如果这是真的,这看起来不是很重要吗?我不会使用无理由随机生成数据的算法,为什么我要使用生成数据的数据转换命令…@gwern。请再次阅读?glm
。特别是我在回答中提到的部分:“对于二项式[…]族,响应也可以指定为一个因子(当第一个级别表示失败,其他所有级别表示成功时)或者作为两列矩阵,各列给出成功和失败的次数。”“对于二项式GLM,当回答是成功的比例时,使用先验权重给出试验次数”。还请重新阅读@DWIN对您的问题和答案的第一条评论。使用的数据当然不仅仅是“虚构的”@gwern,另请参阅。Mymod2
的指定方式与DWIN答案中的模型相同,都基于聚合数据。此外,我创建了一个数据集,每行一个观察值(df1),它是聚合数据的基础,目的是让您看到两个数据集之间的联系以及它们产生的结果。我明白了。使用矩阵输入,然后很容易从N
和Rate
中提取失败和成功的计数-只需考虑列/向量。回顾一下,它看起来非常明显你知道如何将输入作为计数矩阵……如果你使用的第一个支持GLM的程序是GLIM v4,这是“很明显的”。我从来没有使用过GLIM,所以我不知道。是的,这是一个老古董的评论。
set.seed(1)
# one row per observation
df1 <- data.frame(x = sample(c("yes", "no"), 40, replace = TRUE),
y = sample(c("yes", "no"), 40, replace = TRUE),
z = rbinom(n = 40, size = 1, prob = 0.5))
df1
library(plyr)
# aggregated data with one row per treatment combination
df2 <- ddply(.data = df1, .variables = .(x, y), summarize,
n = length(z),
rate = sum(z)/n,
success = n*rate,
failure = n - success)
df2
# three different ways to specify the models,
# which all give the same parameter estimates for x, y and x*y
mod1 <- glm(z ~ x * y, data = df1, family = binomial)
mod2 <- glm(cbind(success, failure) ~ x * y, data = df2, family = binomial)
mod3 <- glm(rate ~ x * y, data = df2, weights = n, family = binomial)
summary(mod1)
summary(mod2)
summary(mod3)