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

背景:我正在运行一个小的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
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)]
#只需输入占位符值即可

newdf
rates$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)
#每观察一行

df1
glm
要求每个案例一行不是真的。有一种方法可以使用聚合数据。请参见
?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,另请参阅。My
mod2
的指定方式与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)