从 Stata 的 haven 导入中提取 "labeled" tibble 列的标签属性
Extract the labels attribute from "labeled" tibble columns from a haven import from Stata
Hadley Wickham 的 haven
包,应用于 Stata 文件,returns 包含许多 "labeled" 类型列的小标题。你可以用 str() 查看这些,例如:
$ MSACMSZ :Class 'labelled' atomic [1:8491861] NA NA NA NA NA NA NA NA NA NA ...
.. ..- attr(*, "label")= chr "metropolitan area size (cmsa/msa)"
.. ..- attr(*, "labels")= Named int [1:7] 0 1 2 3 4 5 6
.. .. ..- attr(*, "names")= chr [1:7] "not identified or nonmetropolitan" "100,000 - 249,999" "250,000 - 499,999" "500,000 - 999,999" ...
如果我能简单地将所有这些带标签的向量提取为因子就好了,但我已经将标签属性的长度与每个向量中唯一值的数量进行了比较,它有时更长,有时更短。所以我认为我需要查看所有这些并决定如何单独处理每个问题。
所以我想将标签属性的值提取到列表中。但是,这个函数:
labels93 <- lapply(cps_00093.df, function(x){attr(X, which="labels", exact=TRUE)})
returns 所有变量均为 NULL。
这是 tibble vs 数据框问题吗?如何将 tibble 列中的这些属性提取到列表中?
请注意,标签向量已命名,我需要标签和名称。
根据@Hack-R 的要求,这里是我的一小段数据,由 dput(我以前从未使用过)转换而来。我应用了这段代码:
filter(cps_00093.df, YEAR==2015) %>%
sample_n(10) %>%
select(HHTENURE, HHINTYPE) -> tiny
dput(tiny, file = "tiny")
生成小文件。嘿!那很简单!我以为这么小的一块很难掰开。
用Notepad++打开tiny,这是我发现的:
structure(list(HHTENURE = structure(c(2L, 1L, 1L, 2L, 1L, 1L,
1L, 2L, 1L, 1L), labels = structure(c(0L, 1L, 2L, 3L, 6L, 7L), .Names = c("niu",
"owned or being bought", "rented for cash", "occupied without payment of cash rent",
"refused", "don't know")), class = "labelled"), HHINTYPE = structure(c(1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), labels = structure(1:3, .Names = c("interview",
"type a non-interview", "type b/c non-interview")), class = "labelled")), row.names = c(NA,
-10L), class = c("tbl_df", "tbl", "data.frame"), .Names = c("HHTENURE",
"HHINTYPE"))
我怀疑这可以通过一点间距提高可读性,但我不想弄乱它,以免不小心破坏相关信息。
虽然我的代码不是很漂亮,但我会尝试回答这个问题。
首先,我创建了一个函数来从单个列中提取命名属性。
ColAttr <- function(x, attrC, ifIsNull) {
# Returns column attribute named in attrC, if present, else isNullC.
atr <- attr(x, attrC, exact = TRUE)
atr <- if (is.null(atr)) {ifIsNull} else {atr}
atr
}
然后一个函数lapply它到所有的列:
AtribLst <- function(df, attrC, isNullC){
# Returns list of values of the col attribute attrC, if present, else isNullC
lapply(df, ColAttr, attrC=attrC, ifIsNull=isNullC)
}
最后我运行它的每个属性。
stub93 <- AtribLst(cps_00093.df, attrC="label", isNullC=NA)
labels93 <- AtribLst(cps_00093.df, attrC="labels", isNullC=NA)
labels93 <- labels93[!is.na(labels93)]
所有列都具有 "label" 属性,但只有一些列属于 "labeled" 类型,因此具有 "labels" 属性。 labels 属性被命名,其中标签与数据的值匹配,名称告诉您这些值的含义。
最初的问题是 'to extract the values of the labels attribute to a list.' 如何解决主要问题(假设 some_df
通过 haven
导入并具有 label
属性)。更新:我现在添加了一种使用包 sjlabelled
.
提取标签向量的方法
library(purrr)
n <- ncol(some_df)
labels_list <- map(1:n, function(x) attr(some_df[[x]], "label") )
# if a vector of character strings is preferable
labels_vector <- map_chr(1:n, function(x) attr(some_df[[x]], "label") )
# to make a simple codebook
library(kable)
variable_name <- names(some_df)
data.frame(variable_name, description = labels_vector) %>%
kable(format = 'markdown')
# UPDATE: another approach with package sjlabelled
library(sjlabelled)
sjlabelled::get_label(some_df)
跳过@omar-waslow上面的回答,但添加了attr_getter
的使用。
如果数据 (some_df
) 是使用 haven
包中的 read_dta
导入的,则小标题中的每一列都有一个名为 [=16= 的 attr
].所以我们拆分数据框,逐列进行。这将创建一个两列数据框,可以将其重新连接(例如,在 pivot_longer 之后)。
library(tidyverse)
label_lookup_map <- tibble(
col_name = some_df %>% names(),
labels = some_df %>% map_chr(attr_getter("label"))
)
Hadley Wickham 的 haven
包,应用于 Stata 文件,returns 包含许多 "labeled" 类型列的小标题。你可以用 str() 查看这些,例如:
$ MSACMSZ :Class 'labelled' atomic [1:8491861] NA NA NA NA NA NA NA NA NA NA ...
.. ..- attr(*, "label")= chr "metropolitan area size (cmsa/msa)"
.. ..- attr(*, "labels")= Named int [1:7] 0 1 2 3 4 5 6
.. .. ..- attr(*, "names")= chr [1:7] "not identified or nonmetropolitan" "100,000 - 249,999" "250,000 - 499,999" "500,000 - 999,999" ...
如果我能简单地将所有这些带标签的向量提取为因子就好了,但我已经将标签属性的长度与每个向量中唯一值的数量进行了比较,它有时更长,有时更短。所以我认为我需要查看所有这些并决定如何单独处理每个问题。
所以我想将标签属性的值提取到列表中。但是,这个函数:
labels93 <- lapply(cps_00093.df, function(x){attr(X, which="labels", exact=TRUE)})
returns 所有变量均为 NULL。
这是 tibble vs 数据框问题吗?如何将 tibble 列中的这些属性提取到列表中?
请注意,标签向量已命名,我需要标签和名称。
根据@Hack-R 的要求,这里是我的一小段数据,由 dput(我以前从未使用过)转换而来。我应用了这段代码:
filter(cps_00093.df, YEAR==2015) %>%
sample_n(10) %>%
select(HHTENURE, HHINTYPE) -> tiny
dput(tiny, file = "tiny")
生成小文件。嘿!那很简单!我以为这么小的一块很难掰开。
用Notepad++打开tiny,这是我发现的:
structure(list(HHTENURE = structure(c(2L, 1L, 1L, 2L, 1L, 1L,
1L, 2L, 1L, 1L), labels = structure(c(0L, 1L, 2L, 3L, 6L, 7L), .Names = c("niu",
"owned or being bought", "rented for cash", "occupied without payment of cash rent",
"refused", "don't know")), class = "labelled"), HHINTYPE = structure(c(1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), labels = structure(1:3, .Names = c("interview",
"type a non-interview", "type b/c non-interview")), class = "labelled")), row.names = c(NA,
-10L), class = c("tbl_df", "tbl", "data.frame"), .Names = c("HHTENURE",
"HHINTYPE"))
我怀疑这可以通过一点间距提高可读性,但我不想弄乱它,以免不小心破坏相关信息。
虽然我的代码不是很漂亮,但我会尝试回答这个问题。
首先,我创建了一个函数来从单个列中提取命名属性。
ColAttr <- function(x, attrC, ifIsNull) {
# Returns column attribute named in attrC, if present, else isNullC.
atr <- attr(x, attrC, exact = TRUE)
atr <- if (is.null(atr)) {ifIsNull} else {atr}
atr
}
然后一个函数lapply它到所有的列:
AtribLst <- function(df, attrC, isNullC){
# Returns list of values of the col attribute attrC, if present, else isNullC
lapply(df, ColAttr, attrC=attrC, ifIsNull=isNullC)
}
最后我运行它的每个属性。
stub93 <- AtribLst(cps_00093.df, attrC="label", isNullC=NA)
labels93 <- AtribLst(cps_00093.df, attrC="labels", isNullC=NA)
labels93 <- labels93[!is.na(labels93)]
所有列都具有 "label" 属性,但只有一些列属于 "labeled" 类型,因此具有 "labels" 属性。 labels 属性被命名,其中标签与数据的值匹配,名称告诉您这些值的含义。
最初的问题是 'to extract the values of the labels attribute to a list.' 如何解决主要问题(假设 some_df
通过 haven
导入并具有 label
属性)。更新:我现在添加了一种使用包 sjlabelled
.
library(purrr)
n <- ncol(some_df)
labels_list <- map(1:n, function(x) attr(some_df[[x]], "label") )
# if a vector of character strings is preferable
labels_vector <- map_chr(1:n, function(x) attr(some_df[[x]], "label") )
# to make a simple codebook
library(kable)
variable_name <- names(some_df)
data.frame(variable_name, description = labels_vector) %>%
kable(format = 'markdown')
# UPDATE: another approach with package sjlabelled
library(sjlabelled)
sjlabelled::get_label(some_df)
跳过@omar-waslow上面的回答,但添加了attr_getter
的使用。
如果数据 (some_df
) 是使用 haven
包中的 read_dta
导入的,则小标题中的每一列都有一个名为 [=16= 的 attr
].所以我们拆分数据框,逐列进行。这将创建一个两列数据框,可以将其重新连接(例如,在 pivot_longer 之后)。
library(tidyverse)
label_lookup_map <- tibble(
col_name = some_df %>% names(),
labels = some_df %>% map_chr(attr_getter("label"))
)