【问题标题】:Convenient way to access variables label after importing Stata data with haven使用 Haven 导入 Stata 数据后访问变量标签的便捷方式
【发布时间】:2016-04-21 10:10:39
【问题描述】:

在 R 中,一些包(例如haven)会在变量(例如haven)中插入一个label 属性,它解释了变量的实质名称。例如,gdppc 可能具有标签 GDP per capita

这非常有用,尤其是在从 Stata 导入数据时。但是,我仍然很难知道如何在我的工作流程中使用它。

  1. 如何快速浏览变量和变量标签?现在我必须做attributes(df$var),但这不太方便一瞥(a la names(df)

  2. 如何在绘图中使用这些标签?同样,我可以使用attr(df$var, "label") 来访问字符串标签。不过好像很麻烦。

是否有任何官方方法可以在工作流程中使用这些标签?我当然可以编写一个环绕attr 的自定义函数,但是将来当包以不同方式实现label 属性时它可能会中断。因此,理想情况下,我希望得到haven(或其他主要软件包)支持的官方方式。

【问题讨论】:

  • 您可以创建类似匹配表的内容,例如lbs <- setNames(_labels_, names(df));然后可以通过例如lbs["var"] 访问标签
  • 不同的包作者以不同的方式实现它。 de_facto R 标准将是 pkg:foreign 中的 read.dta 函数。 haven 是一个相对较新的软件包,目前它似乎没有记录标签计划。
  • @42- read_dta in haven 确实有标签。相比之下,foreign::read.dta 实际上没有。此外,foreign 包不适用于 Stata 13,更不用说 14。
  • 你的问题没有例子。 read.dta 的帮助页面显示该值为:"A data frame with attributes. These will include "datalabel", "time.stamp", "formats", "types", "val.labels", "var.labels" and "version" and may include "label.table" and "expansion.table"
  • 您询问了处理标签的“官方”/惯用方式,这可能最好在foreign 中找到。浏览foreign 文档,他们建议将 readstata13 包用于更高版本的 Stata。大概它也符合在外国发现的任何成语/规范。

标签: r label stata r-haven


【解决方案1】:

使用have包强制到一个因素

haven::as_factor(df$var, levels="label")

【讨论】:

    【解决方案2】:

    labelled 包的目的是提供方便的函数来操作使用haven 导入的变量和值标签。

    此外,questionr 包中的函数 lookfordescribe 也可用于显示变量和值标签。

    【讨论】:

      【解决方案3】:

      labelled 包 (tidyverse) 的简单解决方案

      descriptions <- var_label(data_raw) %>% 
        as_tibble() %>% 
        gather(key = variable, value = description)
      

      【讨论】:

        【解决方案4】:

        在一个简单的函数中使用 sapply 来返回一个变量列表,就像在 Stata 的变量窗口中一样:

        library(dplyr)
        makeVlist <- function(dta) { 
             labels <- sapply(dta, function(x) attr(x, "label"))
              tibble(name = names(labels),
                     label = labels)
        }
        

        【讨论】:

          【解决方案5】:

          purrr package from tidyverse的解决方案:

          df %>% map_chr(~attributes(.)$label)
          

          【讨论】:

            【解决方案6】:

            这是rio 中提到的创新之一(完全披露:我编写了这个包)。基本上,它提供了多种导入变量标签的方式,包括haven的做事方式和foreign的方式。这是一个简单的例子:

            先做一个可重现的例子:

            > library("rio")
            > export(iris, "iris.dta")
            

            使用foreign::read.dta() 导入(通过rio::import()):

            > str(import("iris.dta", haven = FALSE))
            'data.frame':   150 obs. of  5 variables:
             $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
             $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
             $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
             $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
             $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
             - attr(*, "datalabel")= chr ""
             - attr(*, "time.stamp")= chr "15 Jan 2016 20:05"
             - attr(*, "formats")= chr  "" "" "" "" ...
             - attr(*, "types")= int  255 255 255 255 253
             - attr(*, "val.labels")= chr  "" "" "" "" ...
             - attr(*, "var.labels")= chr  "" "" "" "" ...
             - attr(*, "version")= int -7
             - attr(*, "label.table")=List of 1
              ..$ Species: Named int  1 2 3
              .. ..- attr(*, "names")= chr  "setosa" "versicolor" "virginica"
            

            使用 haven::read_dta() 使用其原生变量属性读取,因为属性存储在 data.frame 级别而不是变量级别:

            > str(import("iris.dta", haven = TRUE, column.labels = TRUE))
            'data.frame':   150 obs. of  5 variables:
             $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
             $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
             $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
             $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
             $ Species     :Class 'labelled'  atomic [1:150] 1 1 1 1 1 1 1 1 1 1 ...
              .. ..- attr(*, "labels")= Named int [1:3] 1 2 3
              .. .. ..- attr(*, "names")= chr [1:3] "setosa" "versicolor" "virginica"
            

            使用haven::read_dta() 使用我们(rio 开发人员)发现更方便的替代方法阅读:

            > str(import("iris.dta", haven = TRUE))
            'data.frame':   150 obs. of  5 variables:
             $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
             $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
             $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
             $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
             $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
             - attr(*, "var.labels")=List of 5
              ..$ Sepal.Length: NULL
              ..$ Sepal.Width : NULL
              ..$ Petal.Length: NULL
              ..$ Petal.Width : NULL
              ..$ Species     : NULL
             - attr(*, "label.table")=List of 5
              ..$ Sepal.Length: NULL
              ..$ Sepal.Width : NULL
              ..$ Petal.Length: NULL
              ..$ Petal.Width : NULL
              ..$ Species     : Named int  1 2 3
              .. ..- attr(*, "names")= chr  "setosa" "versicolor" "virginica"
            

            通过将属性移动到 data.frame 的级别,使用attr(data, "label.var") 等更容易访问它们,而不是挖掘每个变量的属性。

            注意:属性的值将为 NULL,因为我只是将本机 R 数据集写入本地文件以使其可重现。

            【讨论】:

            • 您在自己的工作流程中使用rio 吗?团队对跟上你们所提供的所有 IO 包的承诺有多大?我很想有一个像这样的集中式包(因此我尝试了haven),但担心未来的可重复性。
            • @Heisenberg 我们非常致力于保持最新状态,我对向后/向前兼容性非常敏感。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-02-01
            • 2023-03-19
            • 1970-01-01
            • 1970-01-01
            • 2011-01-10
            • 2010-10-10
            相关资源
            最近更新 更多