R:将Anova应用于一个数据集的不同子集并收集输出的功能

时间:2015-09-07 16:04:26

标签: r dplyr glm anova broom

一个常见的任务是必须在数据集的不同子集上执行某种统计分析(如anova,glm或混合模型),并将输出表与汇总系数和p值组合在一个数据帧中。我正在寻找一个通用函数,它将采用模型类型(例如aov(...)lm(...)glm(...)glmer(...))以及系数的特定输出项根据一个数据集中的某些分组变量,必须为每个重复分析返回p值。

假设我有一个数据框,我想在数据框data中对不同级别的因子“复制”进行某种分析:

data(iris)
library(car)
data=data.frame()
for (i in 1:10) {data=rbind(data,cbind(replicate=i,iris))}

使用broom+dplyr,我可以,例如对此数据框的每个子集执行anova(按复制分组)并使用

保留术语“Species”的p值
library(devtools)
install_github("dgrtwo/broom")
library(broom)
library(dplyr)

group_by(data, replicate) %>% do(tidy(Anova(aov(Sepal.Length ~ Species, data = .),type="III"))) %>% filter(term=="Species")

Source: local data frame [10 x 6]
Groups: replicate [10]

   replicate    term    sumsq    df statistic      p.value
       (int)   (chr)    (dbl) (dbl)     (dbl)        (dbl)
1          1 Species 189.6364     2  362.6614 2.580311e-94
2          2 Species 189.6364     2  362.6614 2.580311e-94
3          3 Species 189.6364     2  362.6614 2.580311e-94
4          4 Species 189.6364     2  362.6614 2.580311e-94
5          5 Species 189.6364     2  362.6614 2.580311e-94
6          6 Species 189.6364     2  362.6614 2.580311e-94
7          7 Species 189.6364     2  362.6614 2.580311e-94
8          8 Species 189.6364     2  362.6614 2.580311e-94
9          9 Species 189.6364     2  362.6614 2.580311e-94
10        10 Species 189.6364     2  362.6614 2.580311e-94

(我在这里使用了10个相同的数据子集)

我正在寻找更通用的函数“Anovabygroup”,它将采用数据帧,分组变量(此处replicate,但它也可能是几个分组的组合变量),要运行的模型的类型(例如在这种情况下'aov(Sepal.Length ~ Species, data = .)',但它也可以是lm,glm,lme,lmer或glmer模型或由Anova()处理的任何其他模型)和返回系数和p值的因素(可能选项“all”返回所有内容)作为参数(给出的任何其他选项可以传递给Anova的调用)。有人会用任何机会知道如何做到这一点,使用类似于上面使用的代码,但是通用化了这些参数吗?我不知道怎么做的主要事情是传递模型(例如在这种情况下`'aov(Sepal.Length~Species,data =。)')作为参数并进行评估。或者它可能已经存在于某个包中?我认为这可能很有用,因为我总是发现自己一遍又一遍地编写这个任务......

PS我使用了github版本的扫帚包,因为当前的CRAN版本似乎没有很好地处理Anova输出

1 个答案:

答案 0 :(得分:4)

答案:

您可以通过创建解析文本输入的包装函数来解决此问题。 在这里,我使用evalglm

理想情况下,该函数还会检查传递的表达式(lmAnova等)的有效性,但这里有一个示例函数可以帮助您入门。

它还允许您按照要求将其他选项传递给anova_wrapper <- function(data, model_expression_as_string, grouping_variable,...) { f_wrap <- paste0('function(.) {',model_expression_as_string,'}') %>% parse(text=.) %>% eval data %>% group_by_(grouping_variable) %>% do(f_wrap(.) %>% Anova(...=...) %>% tidy) %>% return }

data=data.frame()
for (i in 1:10) {data=rbind(data,cbind(replicate=i,iris))}

aov_model_expression_as_string = 'aov(Sepal.Length ~ Species, data = .)'
lm_model_expression_as_string = 'lm(Sepal.Length ~ Sepal.Width + Petal.Length , data = .)'
grouping_variable = 'replicate'


data %>% 
    anova_wrapper(model_expression_as_string = aov_model_expression_as_string,
                  grouping_variable = grouping_variable,type="III")



    Source: local data frame [30 x 6]
    Groups: replicate [10]

    replicate        term      sumsq    df statistic       p.value
    (int)       (chr)      (dbl) (dbl)     (dbl)         (dbl)
    1          1 (Intercept) 1253.00180     1 4728.1630 1.134286e-113
    2          1     Species   63.21213     2  119.2645  1.669669e-31
    3          1   Residuals   38.95620   147        NA            NA
    4          2 (Intercept) 1253.00180     1 4728.1630 1.134286e-113
    5          2     Species   63.21213     2  119.2645  1.669669e-31
    6          2   Residuals   38.95620   147        NA            NA
    7          3 (Intercept) 1253.00180     1 4728.1630 1.134286e-113
    8          3     Species   63.21213     2  119.2645  1.669669e-31
    9          3   Residuals   38.95620   147        NA            NA
    10         4 (Intercept) 1253.00180     1 4728.1630 1.134286e-113
    ..       ...         ...        ...   ...       ...           ...

实施例

使用您的示例代码(感谢您发布好的代码!):

lm

使用aov代替Anovadata %>% anova_wrapper(model_expression_as_string = lm_model_expression_as_string, grouping_variable = grouping_variable,type="III") replicate term sumsq df statistic p.value (int) (chr) (dbl) (dbl) (dbl) (dbl) 1 1 Sepal.Width 8.19627 1 73.78707 1.163254e-14 2 1 Petal.Length 84.42733 1 760.05861 5.847914e-60 3 1 Residuals 16.32876 147 NA NA 4 2 Sepal.Width 8.19627 1 73.78707 1.163254e-14 5 2 Petal.Length 84.42733 1 760.05861 5.847914e-60 6 2 Residuals 16.32876 147 NA NA 7 3 Sepal.Width 8.19627 1 73.78707 1.163254e-14 8 3 Petal.Length 84.42733 1 760.05861 5.847914e-60 9 3 Residuals 16.32876 147 NA NA 10 4 Sepal.Width 8.19627 1 73.78707 1.163254e-14 .. ... ... ... ... ... ... 的不同参数:

Child childAlias = null;
Parent parentAlias = null;
int[] parentIds = new int[] {1, 2, 3};

var temp = sess.QueryOver<Parent>()
    .JoinQueryOver(p => p.Children, () => childAlias)
    .WhereRestrictionOn(c => c.Parent.ID).IsIn(parentIds)
    .Select(Projections.ProjectionList()
        .Add(Projections.GroupProperty(Projections.Property<Parent>(x => x.ID)))
        .Add(Projections.Count(() => childAlias.ID)))
    .List<object[]>()
    .Select(x => new KeyValuePair<int,int>((int)x[0], (int)x[1]));

我经常在monte carlo模拟中反复使用这些类型的回归/ anovas,但我通常会为每种分析创建一个单独的函数。 R社区可能会对重复进行这些分析的一揽子计划感兴趣!