从数组生成数据框以进行逻辑回归

时间:2012-12-09 20:46:56

标签: r

假设您有一个像

这样的数组
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 个答案:

答案 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对象。

修改

以下循环遍历datMvalue列之外的所有列,重复值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