将多个数据帧提供给glm()和odds.ratio() - 类

时间:2017-10-24 13:02:39

标签: r

我有一个数据框(mtcars),我可以使用问题包来获得优势比(OR),包括95%的置信区间。

我希望通过三级齿轮变量对mtcars数据帧进行分组,并为这三个新数据帧获得与单个数据帧相同的输出类型。

问题是odds.ratio()接受glm lm类对象但不接受列表类对象。我尝试在myFunc中的glm()外面放置odds.ratio(),但它不起作用。

非常感谢任何帮助。

单个数据框的代码:

library(questionr)
data(mtcars)
reg2 <- glm(am ~ carb + cyl, data=mtcars, family=binomial)
odds.ratio(reg2)

多个新数据框的当前代码:

GearList <- split(mtcars, paste0("df", mtcars$gear))
MyFunc <- function(df) {odds.ratio(glm(am ~ carb + cyl, data=df, family=binomial))
}
lapply(GearList, MyFunc)

2 个答案:

答案 0 :(得分:0)

虽然这没有回答如何停止获得有关置信区间计算的错误的问题,如评论中所述,这里是一个以更优雅的方式计算数据子集的比值比的解决方案(至少在我看来):

library(tidyverse)
mtcars %>%
  group_by(gear) %>%
  # create list columns with each subset of data
  nest() %>%
  # create a new list column with the glm results from each group
  mutate(glm = map(
    .x = data,
    .f = function(x){
      glm(am ~ carb + cyl, data = x, family = binomial)
    }
  )) %>%
  # create odds_ratio list column
  mutate(odd_ratio = map(glm, odds.ratio))

如上所述,这仍然会给你上面的错误,因为数据的大小似乎是问题而不是方法本身。如果您选择其他数据集,则应该可以使用

答案 1 :(得分:0)

只是为了表明您的代码确实有效:

df <- data.frame(group = factor(sample(1:3, 1000, replace = T), 1:3, labels = c("a", "b", "c")), 
                 int = sample(0:1, 1000, replace = T), x1 = rnorm(1000, 5, 3), x2 = runif(1000, 1, 100))

> head(df)
  group int          x1       x2
1     a   1  5.61526037 92.62681
2     c   0  0.55239463 96.64969
3     a   0  0.66831207 48.53553
4     c   0 -0.07698548 93.93554
5     a   1  0.57997037 40.25295
6     b   0  2.65677633 88.57560

reg2 <- glm(int ~ x1 + x2, data = df, family = binomial)
odds.ratio(reg2)

> odds.ratio(reg2)
Waiting for profiling to be done...
                 OR   2.5 % 97.5 %      p
(Intercept) 0.82392 0.59350 1.1421 0.2457
x1          1.03428 0.99280 1.0778 0.1073
x2          0.99954 0.99520 1.0039 0.8349

grouplist <- split(df, df$group)
MyFunc <- function(df) {odds.ratio(glm(int ~ x1 + x2, data=df, family=binomial))
}
lapply(grouplist, MyFunc)

> lapply(grouplist, MyFunc)
Waiting for profiling to be done...
Waiting for profiling to be done...
Waiting for profiling to be done...
$a
                 OR   2.5 % 97.5 %      p
(Intercept) 1.04981 0.59169 1.8637 0.8678
x1          1.00217 0.93118 1.0786 0.9537
x2          0.99645 0.98895 1.0040 0.3545

$b
                 OR   2.5 % 97.5 %      p
(Intercept) 0.77073 0.43629 1.3533 0.3659
x1          1.05588 0.98380 1.1346 0.1340
x2          1.00066 0.99310 1.0083 0.8647

$c
                 OR   2.5 % 97.5 %      p
(Intercept) 0.68406 0.38479 1.2054 0.1912
x1          1.04820 0.97757 1.1252 0.1881
x2          1.00169 0.99416 1.0093 0.6617

那就是说,我认为你的例子中的应用程序实际上不值得编写自定义函数。只需将代码直接写入lapply调用:

即可
lapply(grouplist, function(x) odds.ratio(glm(int ~ x1 + x2, data=x, family=binomial)))

在我看来,函数应该很少包含数据向量作为常量(仅在数学过程中有意义)。当您的目标是循环遍历多个数据集,变量或其他对象时,要么将快速临时函数写入循环(如上所示),或者,如果您认为您将在不同的组合中经常进行此类操作,编写一个包含更多变量的函数:

ORglm <- function(formula, dataset, family = "binomial"){
  questionr::odds.ratio(glm(as.formula(formula), data = dataset, family = family))
}

这样,你

一个。不必加载questionr - 包来使用该功能,
湾可以自由更改公式而无需编辑函数本身,并且 C。甚至可以更改您想要计算的glm的族。

如果需要,您甚至可以包含更多选项。这比您的方法只需要几分钟,但可能在将来为您节省很多麻烦。