假设您有一个像
这样的数组dat <- array(c(126, 100, 35, 61, 908, 688, 497, 807, 913, 747, 336, 598, 235, 172, 58, 121,402, 308, 121, 215, 182, 156, 72, 98, 60, 99, 11, 43, 104, 89, 21, 36), dim = c(2, 2, 8),dimnames = list(a = c(1, 0), b = c(1, 0), c = 1:8))
> > dat
, , c = 1
b
a 1 0
1 126 35
0 100 61
, , c = 2
b
a 1 0
1 908 497
0 688 807
, , c = 3
b
a 1 0
1 913 336
0 747 598
, , c = 4
b
a 1 0
1 235 58
0 172 121
, , c = 5
b
a 1 0
1 402 121
0 308 215
, , c = 6
b
a 1 0
1 182 72
0 156 98
, , c = 7
b
a 1 0
1 60 11
0 99 43
, , c = 8
b
a 1 0
1 104 21
0 89 36
并且您希望适合逻辑回归来预测a。有没有一种简单的方法可以从这个数组生成数据帧以在glm中使用?即数据框,如
a b c
1 1 1 for 126 rows then
...
0 1 1 for 100 rows, etc.
基本上,当给定带有计数的表时,我需要获取数据以适应逻辑回归。看起来应该有一种简单的方法,无需手动生成数据。
感谢
答案 0 :(得分:4)
一种方法是从melt
包中的reshape2
函数开始:
library(reshape2)
datM <- melt(dat)
head(datM, 2)
# a b c value
# 1 1 1 1 126
# 2 0 1 1 100
然后dcast
数据来获取一行结果的数量:
dat2 <- dcast(datM, b + c ~ a)
head(dat2, 2)
# b c 0 1
# 1 0 1 61 35
# 2 0 2 807 497
然后,您可以使用此数据执行glm
,其中响应是一个2列矩阵,给出成功和失败的次数:
response <- as.matrix(dat2[, c(4, 3)])
bb <- dat2[, "b"]
cc <- dat2[, "c"]
glm1 <- glm(response ~ bb + cc, family = binomial(link = "logit"))
但是,模型自由度(和对数似然等)不会反映您在问题中要求的数据结构。要获得您想要的特定数据结构,您可以返回datM
对象。
修改强>
以下循环遍历datM
除value
列之外的所有列,重复值datM$value
次:
datRep <- lapply(datM[-grep("value", names(datM))], rep, times = datM$value)
然后cbind
返回matrix
并转换为data.frame
以获取您想要的数据结构:
dat3 <- as.data.frame(do.call(cbind, datRep))
glm2 <- glm(a ~ b + c, data = dat3, family = binomial(link = "logit"))
两个模型的系数相同:
> coef(glm1)
(Intercept) bb cc
-0.43854838 0.77039283 -0.03328575
> coef(glm2)
(Intercept) b c
-0.43854838 0.77039283 -0.03328575
但是,如上所述,自由度等不会是:
> glm1$deviance
[1] 29.39535
> glm2$deviance
[1] 11381.87
答案 1 :(得分:1)
丑陋的罪,但你做了这个例子所需要的。
dat1 <- data.frame(value = as.vector(dat),
a=dimnames(dat)$a,
b=rep(dimnames(dat)$b, each=length(dimnames(dat)$a)),
c=rep(dimnames(dat)$c, each=length(dimnames(dat)$a)*length(dimnames(dat)$b)))
最好使用melt
,就像@BenBarnes的回答一样。这更灵活,避免了因素的产生。
dat1 <- melt(dat)
然后,要获取展开的行,您可以使用rep
dat2 <- data.frame(a=rep(dat1$a, dat1$value),
b=rep(dat1$b, dat1$value),
c=rep(dat1$c, dat1$value))
答案 2 :(得分:1)
使用基本函数获取计数数据的另一种替代方法,然后可以在@ MatthewLundberg的答案中进行扩展:
dat1 <- data.frame(do.call(expand.grid,dimnames(dat)),value=as.vector(dat))
a b c value
1 1 1 1 126
2 0 1 1 100
3 1 0 1 35
4 0 0 1 61
5 1 1 2 908
...
从以前的回答中偷走......
dat2 <- data.frame(a=rep(dat1$a, dat1$value),
b=rep(dat1$b, dat1$value),
c=rep(dat1$c, dat1$value))
答案 3 :(得分:1)
进行第一部分,将数组转换为data.frame
的最小方法是使用as.data.frame.table
。然后按@MatthewLundberg或@thelatemail建议继续。
df0 <- as.data.frame.table(dat)
head(df0)
# a b c Freq
# 1 1 1 1 126
# 2 0 1 1 100
# 3 1 0 1 35
# 4 0 0 1 61
# 5 1 1 2 908
# 6 0 1 2 688