【问题标题】:R - How to contrast code factors and retain meaningful labels in output summaryR - 如何对比代码因子并在输出摘要中保留有意义的标签
【发布时间】:2014-07-01 17:13:14
【问题描述】:

好的,大家,一劳永逸,你如何(强调你,因为我确信有不止一种方法可以实现这一点)对比代码(处理、求和、helmert 等)并保留一个有意义的glm 函数中的因子标签(以便您可以对效果做出有意义的解释)?

我知道我可以使用 level() 来了解哪个因子水平是参考,但是当我开始涉及具有 5 或 10 个水平的因子及其相互作用时,这会变得乏味。

这是我的意思的一个快速的两个因素示例

outcome <- c(1,0,0,1,1,0,0,0,1, 0, 0, 1)
firstvar <- c("A", "B", "C", "C", "B", "B", "A", "A", "C", "A", "C", "B")
secondvar <- c("D", "D", "E", "F", "F", "E", "D", "E", "F", "F", "D", "E")
df <- as.data.frame(cbind(outcome, firstvar, secondvar))

df$firstvar <- as.factor(df$firstvar)
df$secondvar <- as.factor(df$secondvar)

#not coded manually (and default appears to be dummy or treatment coding)
#gives meaningful factor labels in summary function
summary(glm(outcome ~ firstvar*secondvar, data=df, family="binomial"))

#effects coded
#does not give meaningful factor labels
contrasts(df$firstvar)=contr.sum(3)
contrasts(df$secondvar)=contr.sum(3)
summary(glm(outcome ~ firstvar*secondvar, data=df, family="binomial"))

#dummy coded
contrasts(df$firstvar)=contr.treatment(3); 
contrasts(df$secondvar)=contr.treatment(3); 
summary(glm(outcome ~ firstvar*secondvar, data=df, family="binomial"))

我们将不胜感激任何和所有建议。这个问题困扰了我一段时间,我确信有一个简单的(ish)解决方案。

【问题讨论】:

    标签: r r-factor


    【解决方案1】:

    嗯,简单的答案(至少对于contr.treatment)是您应该将因子级别传递给函数,而不仅仅是总数。在大多数情况下,这将正确设置级别名称。例如

    contr.treatment(levels(df$firstvar))
    
    #   B C
    # A 0 0
    # B 1 0
    # C 0 1
    

    然后 R 使用列名作为回归摘要中系数的标签/后缀。但是,即使传递标签,contr.sum 也不喜欢设置列名。不过,我们可以在这里创建自己的包装器。

    named.contr.sum<-function(x, ...) {
        if (is.factor(x)) {
            x <- levels(x)
        } else if (is.numeric(x) & length(x)==1L) {
            stop("cannot create names with integer value. Pass factor levels")
        }
        x<-contr.sum(x, ...)
        colnames(x) <- apply(x,2,function(x) 
             paste(names(x[x>0]), names(x[x<0]), sep="-")
        )
        x
    }
    

    这里我们基本上是在调用contr.sum 并且只是将列名添加到结果中(加上一些错误检查)。你可以运行它

    named.contr.sum(levels(df$firstvar))
    
    #   A-C B-C
    # A   1   0
    # B   0   1
    # C  -1  -1
    

    我决定使用“A-C”和“B-C”作为标签,但如果您愿意,您可以在代码中更改它。然后运行

    contrasts(df$firstvar)=named.contr.sum(levels(df$firstvar))
    contrasts(df$secondvar)=named.contr.sum(levels(df$secondvar))
    
    summary(glm(outcome ~ firstvar*secondvar, data=df, family="binomial"))
    

    会给你

    呼叫:

    glm(formula = outcome ~ firstvar * secondvar, family = "binomial", 
        data = df)
    
    Coefficients:
                               Estimate Std. Error z value Pr(>|z|)
    (Intercept)              -6.855e+00  5.023e+03  -0.001    0.999
    firstvarA-C              -6.855e+00  6.965e+03  -0.001    0.999
    firstvarB-C               6.855e+00  6.965e+03   0.001    0.999
    secondvarD-F             -6.855e+00  6.965e+03  -0.001    0.999
    secondvarE-F             -6.855e+00  6.965e+03  -0.001    0.999
    firstvarA-C:secondvarD-F  2.057e+01  8.473e+03   0.002    0.998
    firstvarB-C:secondvarD-F -1.371e+01  1.033e+04  -0.001    0.999
    firstvarA-C:secondvarE-F  7.072e-10  1.033e+04   0.000    1.000
    firstvarB-C:secondvarE-F  6.855e+00  8.473e+03   0.001    0.999
    

    【讨论】:

    • 谢谢你!当您说您“决定使用 'A-C' 和 'B-C' 作为标签时,您在代码中的哪个位置调用它?我习惯使用 relevel 并重新运行我的对比来对参考级别进行分类。
    • 我应该更清楚。它在paste(names(x[x&gt;0]), names(x[x&lt;0]), sep="-") 行中。我使用带有“1”的值的行名减去带有值“-1”的行名。粘贴将“-”放在这些值之间。
    【解决方案2】:

    这是一个老话题,但我需要为以后可能阅读的任何人澄清一下。

    即使在传递标签时,contr.sum 也不喜欢设置列名。

    这种现象的发生有充分的理由 Sum coding 将 n-1 水平与 grand mean 进行比较,例如B-mean,C-mean,所以用其他方式标记 contr.sum 是错误的。

    各类编码参考UCLA手册R LIBRARY CONTRAST CODING SYSTEMS FOR CATEGORICAL VARIABLES

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-12
      • 2021-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多