【问题标题】:Confusion between factor levels and factor labels因子水平和因子标签之间的混淆
【发布时间】:2011-08-17 16:37:37
【问题描述】:

R 中因子的级别和标签之间似乎存在差异。 到目前为止,我一直认为水平是因子水平的“真实”名称,标签是用于输出的名称(例如表格和绘图)。显然,情况并非如此,如下例所示:

df <- data.frame(v=c(1,2,3),f=c('a','b','c'))
str(df)
'data.frame':   3 obs. of  2 variables:
 $ v: num  1 2 3
 $ f: Factor w/ 3 levels "a","b","c": 1 2 3

df$f <- factor(df$f, levels=c('a','b','c'),
  labels=c('Treatment A: XYZ','Treatment B: YZX','Treatment C: ZYX'))
levels(df$f)
[1] "Treatment A: XYZ" "Treatment B: YZX" "Treatment C: ZYX"

我认为在编写脚本时仍然可以以某种方式访问​​级别('a'、'b'、'c'),但这不起作用:

> df$f=='a'
[1] FALSE FALSE FALSE

但这确实:

> df$f=='Treatment A: XYZ' 
[1]  TRUE FALSE FALSE

所以,我的问题包括两部分:

  • 级别和标签有什么区别?

  • 脚本和输出的因子级别是否可以有不同的名称?

背景:对于较长的脚本,编写具有较短因子级别的脚本似乎要容易得多。但是,对于报告和绘图,这个简短的因子水平可能不够,应该用更精确的名称替换。

【问题讨论】:

    标签: r r-factor r-faq


    【解决方案1】:

    非常短:级别是输入,标签是factor() 函数中的输出。一个因子只有一个level 属性,该属性由factor() 函数中的labels 参数设置。这与 SPSS 等统计软件包中的标签概念不同,一开始可能会造成混淆。

    你在这行代码中做了什么

    df$f <- factor(df$f, levels=c('a','b','c'),
      labels=c('Treatment A: XYZ','Treatment B: YZX','Treatment C: ZYX'))
    

    告诉 R 有一个向量 df$f

    • 你想转换成一个因子,
    • 其中不同的级别被编码为 a、b 和 c
    • 并且您希望将其级别标记为治疗 A 等。

    因子函数将查找值 a、b 和 c,将它们转换为数值因子类,并将标签值添加到因子的 level 属性中。此属性用于将内部数值转换为正确的标签。但是如您所见,没有label 属性。

    > df <- data.frame(v=c(1,2,3),f=c('a','b','c'))    
    > attributes(df$f)
    $levels
    [1] "a" "b" "c"
    
    $class
    [1] "factor"
    
    > df$f <- factor(df$f, levels=c('a','b','c'),
    +   labels=c('Treatment A: XYZ','Treatment B: YZX','Treatment C: ZYX'))    
    > attributes(df$f)
    $levels
    [1] "Treatment A: XYZ" "Treatment B: YZX" "Treatment C: ZYX"
    
    $class
    [1] "factor"
    

    【讨论】:

    • 感谢您的快速答复!我想我现在了解级别和标签的目的。也许有什么建议可以在不手动编辑表名和绘图图例的情况下使输出更易于阅读?
    • 我经常会在绘制/创建标签之前转换关卡,例如操作时将级别保持为“a”,“b”,“c”,然后使用 levels(f)
    • 我都想过,但两种方法都有缺点。第一个在绘制大量图表时可能会变得乏味,而第二个可能会在脚本涉及大量数据聚合时变得乏味。但显然没有办法轻易避免这种情况,所以我会接受你的建议。 :)
    • @42- 我不确定您所说的“数值”是什么意思。如果您指的是因子中的内部值,那么这正是我上面所说的。因此提到了 internal 数值。如果您指定 levels 参数,则您在输入中提供必须与 labels 参数匹配的值。 R 保留标签(作为属性levels,并且存在混淆)并在内部存储整数代码。这些整数代码与原始值无关,无论它们是什么类型。我想你误会了我。
    • 道歉。你写的也是我的理解,现在我正在重新阅读你的问题,我看不出我认为你所说的不同之处。我将删除我的评论,因为它几乎没有添加任何内容。
    【解决方案2】:

    我编写了一个包“lfactors”,它允许您引用级别或标签。

    # packages
    install.packages("lfactors")
    require(lfactors)
    
    flips <- lfactor(c(0,1,1,0,0,1), levels=0:1, labels=c("Tails", "Heads"))
    # Tails can now be referred to as, "Tails" or 0
    # These two lines return the same result
    flips == "Tails"
    #[1]  TRUE FALSE FALSE  TRUE  TRUE FALSE
    flips == 0 
    #[1]  TRUE FALSE FALSE  TRUE  TRUE FALSE
    

    请注意,lfactor 要求级别为数字,以免与标签混淆。

    【讨论】:

    • 这是一个不错的软件包,感谢您发布它(并编写它)。似乎这种功能应该是 R 因素所固有的——很高兴看到一个包提供了这种带有内置等效检查的名称-值对映射。
    • 天啊!我对使用 lfactors 感到很兴奋,直到我注意到它“要求级别是数字的”。需要发布风格标签(希腊字母、斜体、上标等)的数字是一个很好的用例,用于仍然可以包括文本级别的因素系统(后者可以通过使数据表更具可读性来帮助最大限度地减少错误)。跨度>
    • 好奇的实验鼠,级别是数字,标签是文本。你能想出一个有问题的代码示例吗?
    • 这应该完全包含在base或ggplot中。
    【解决方案3】:

    只是想分享一种我通常用来处理这个问题的技术,即为脚本和漂亮打印的因子变量的级别使用不同的名称:

    # Load packages
    library(tidyverse)
    library(sjlabelled)
    library(patchwork)
    
    # Create data frames
    df <- data.frame(v = c(1, 2, 3), f = c("a", "b", "c"))
    df_labelled <- data.frame(v = c(1, 2, 3), f = c("a", "b", "c")) %>%
      val_labels(
        # levels are characters
        f = c(
          "a" = "Treatment A: XYZ", "b" = "Treatment B: YZX", 
          "c" = "Treatment C: ZYX"
        ), 
        # levels are numeric
        v = c("1" = "Exp. Unit 1", "2" = "Exp. Unit 2", "3" = "Exp. Unit 3")
      )
    
    # df and df_labelled appear exactly the same when printed and nothing changes
    # in terms of scripting
    df
    #>   v f
    #> 1 1 a
    #> 2 2 b
    #> 3 3 c
    df_labelled
    #>   v f
    #> 1 1 a
    #> 2 2 b
    #> 3 3 c
    
    # Now, let's take a look at the structure of df and df_labelled
    str(df)
    #> 'data.frame':    3 obs. of  2 variables:
    #>  $ v: num  1 2 3
    #>  $ f: chr  "a" "b" "c"
    str(df_labelled) # notice the attributes
    #> 'data.frame':    3 obs. of  2 variables:
    #>  $ v: num  1 2 3
    #>   ..- attr(*, "labels")= Named num [1:3] 1 2 3
    #>   .. ..- attr(*, "names")= chr [1:3] "Exp. Unit 1" "Exp. Unit 2" "Exp. Unit 3"
    #>  $ f: chr  "a" "b" "c"
    #>   ..- attr(*, "labels")= Named chr [1:3] "a" "b" "c"
    #>   .. ..- attr(*, "names")= chr [1:3] "Treatment A: XYZ" "Treatment B: YZX" "Treatment C: ZYX"
    
    # Lastly, create ggplots with and without pretty names for factor levels
    p1 <- df_labelled %>% # or, df
      ggplot(aes(x = f, y = v)) + 
      geom_point() + 
      labs(x = "Treatment", y = "Measurement")
    p2 <- df_labelled %>%
      ggplot(aes(x = to_label(f), y = to_label(v))) + 
      geom_point() + 
      labs(x = "Treatment", y = "Experimental Unit")
    
    p1 / p2
    

    reprex package (v2.0.0) 于 2021-08-17 创建

    【讨论】:

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