3

假设你有一个数组

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.

基本上,当给定带有计数的表时,我需要获取适合逻辑回归的数据。似乎应该有一种简单的方法来做到这一点,而无需手动生成数据。

谢谢

4

4 回答 4

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

然后,您可以使用此数据执行 a 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为 amatrix并转换为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
于 2012-12-09T22:29:51.033 回答
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))
于 2012-12-09T22:25:01.157 回答
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))
于 2012-12-09T23:27:41.723 回答
1

承担第一部分的最小方法是将数组转换data.frameas.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
于 2016-03-02T12:51:17.707 回答