5

haven::read_dtalabel支持使用属性将变量标签从 Stata 导入 R。Rstudio 还支持在视图窗格中显示这些标签。

dplyr::bind_rows但是,当使用(或)绑定两个数据帧时rbind_all,不会保留标签。这是一个错误吗?

library(dplyr)
id <- 1:5
attr(id, "label") <- "unit id"

df1 <- tbl_df(data.frame(id)) # label is fine
df1$id
# [1] 1 2 3 4 5
# attr(,"label")
# [1] "unit id"

df2 <- tbl_df(data.frame(id)) # label is fine
df2$id
# [1] 1 2 3 4 5
# attr(,"label")
# [1] "unit id"

df_bound <- bind_rows(df1, df2) # label is gone
df_bound$id
# [1] 1 2 3 4 5 1 2 3 4 5
4

4 回答 4

2

一种解决方法是使用rbind而不是bind_rows. 然后,您必须确保列名相同。

用于setdiff(names(df1), names(df2))获取 indf1但不在 in 的列名df2setdiff(names(df2), names(df1))反之亦然。

于 2019-01-31T13:03:43.203 回答
1

Daniel Lüdeckesjlabelled包是处理标记数据时此类问题的一个很好的解决方案。我将该功能用于类似的问题:copy_labels

library(dplyr)  
library(sjlabelled) 
id <- 1:5  
attr(id, "label") <- "unit id"  
df1 <- tbl_df(data.frame(id))  
str(df1)   
# tibble [5 × 1] (S3: tbl_df/tbl/data.frame)  
# $ id: int [1:5] 1 2 3 4 5  
# ..- attr(*, "label")= chr "unit id"  
df2 <- tbl_df(data.frame(id)) # label is fine  
df_bound <- bind_rows(df1, df2) # label is gone  
str(df_bound)  
# tibble [10 × 1] (S3: tbl_df/tbl/data.frame)  
#  $ id: int [1:10] 1 2 3 4 5 1 2 3 4 5   

df_bound <- copy_labels(df_bound, df1)  
df_bound_labelled <- df_bound %>% mutate_at(vars(id), as_labelled)
str(df_bound_labelled)  
# tibble [10 × 1] (S3: tbl_df/tbl/data.frame)  
# $ id: int [1:10] 1 2 3 4 5 1 2 3 4 5  
#  ..- attr(*, "label")= chr "unit id"  
于 2020-05-17T20:29:49.173 回答
0

本着与@TommyFlyn 给出的答案相同的精神,还有labelled由 Joseph Larmarange 维护的包,特别是由 Daniel Ludecke ( sjlabelled) 和 Hadley Wickham 编写的。

假设df.ls,使用 导入的数据框列表haven::read_dta,它们有很多共同的变量,但不是全部。在这种情况下,使用它很方便,dplyr::bind_rows它不需要在所有数据帧中具有相同的变量(列)。正如OP所提到的,问题在于它“删除”了标签。我要补充一点,这仅适用于列表的数据框共有的变量。当某些变量在某些数据框中但不在其他数据框中时,它们会保留其标签。

我们可以使用

common_col_names <- ## get the names of the columns common to all the dfs
    Reduce(intersect, lapply(df.ls,names))
library(labelled)
labs.ls <- ## a list of lists
    lapply(
        df.ls,
        function(x) {
            labelled::var_label(
                          x[, common_col_names],
                          unlist = FALSE
                      )
        }
    )

假设给定变量在所有数据帧中保持相同的标签df.ls。因此,使用common_col_names以及标签是恒定的假设意味着 的所有元素(列表)labs.ls都是相同的。

设置unlist = FALSE(默认)允许在列表(而不是字符向量)中有不同的标签,这反过来又允许以下(来自labelled文档): name 将匹配数据框的一列将被考虑在内。如果 value 是字符向量,则标签应与 data.frame 的列的顺序相同。'' 如果列表的所有数据帧中的列/变量不相同,这将非常方便。

请注意,检查labs.ls对于检查标签是否在数据帧中实际上保持相同很有用。

然后,您只需绑定列表中的不同数据框并分配提取的标签:

df <- dplyr::bind_rows(df.ls)
labelled::var_label(df) <- labs.ls[[1]]

这里我们使用labs.ls[[1]],但是由于我们只考虑所有数据帧共有的变量,并且我们假设这些变量的标签是恒定的,请注意可以使用 2、3、...,length(df.ls)而不是 1。

于 2021-11-25T10:57:52.663 回答
-1

sjmisc::add_rows具有与 相似的语法dplyr::bind_rows,并保留变量和值标签属性。

于 2021-05-31T09:27:06.513 回答