如何一步将df_old的变量标签批量赋值给df_new对应变量?
问题:将dataframe的变量标签批量迁移到另一个dataframe
我有一个带变量标签的dataframe(df_old),想把这些标签提取出来赋值给另一个dataframe(df_new)的对应变量。尝试在循环里执行以下代码但没生效:
attr(df_new[ , j], "label") <- attr(df_old[ , j], "label")
后来用下面的方法绕开了问题:
Tmp <- data.frame(df_old[ , j ]) names(Tmp) <- "Var" attr(df_new[ , j], "label") <- attr(Tmp$Var, "label")
请问有没有一步到位的实现方法?
补充示例代码
df_old <- structure(list(A1_1 = structure(c(1, 3, 2, 1, 6, 1, 5, 7, 1, 1), label = "Use Facebook", format.spss = "F1.0", display_width = 1L, labels = c(`Every day` = 1, `A few times a week` = 2, `A few times a month` = 3, `Once a month` = 4, `Every few months` = 5, `Less often` = 6, `I never do this activity` = 7 ), class = c("haven_labelled", "vctrs_vctr", "double")), A1_2 = structure(c(1, 4, 1, 7, 7, 1, 1, 7, 1, 6), label = "Use Instagram", format.spss = "F1.0", display_width = 1L, labels = c(`Every day` = 1, `A few times a week` = 2, `A few times a month` = 3, `Once a month` = 4, `Every few months` = 5, `Less often` = 6, `I never do this activity` = 7 ), class = c("haven_labelled", "vctrs_vctr", "double")), A1_3 = structure(c(1, 1, 2, 7, 7, 6, 1, 7, 2, 1), label = "Use TikTok", format.spss = "F1.0", display_width = 1L, labels = c(`Every day` = 1, `A few times a week` = 2, `A few times a month` = 3, `Once a month` = 4, `Every few months` = 5, `Less often` = 6, `I never do this activity` = 7 ), class = c("haven_labelled", "vctrs_vctr", "double"))), row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame"), label = "TvTPQ2_0.sav") df_new <- data.frame(matrix(0, ncol = ncol(df_old), nrow = nrow(df_old) )) names(df_new) <- paste0(names(df_old),"_new")
解决方案
方法1:基础循环+直接引用列
先提取df_old的所有变量标签,再通过循环直接给df_new的列赋值,注意用[[j]]而非[,j]来避免复制副本的问题:
# 提取df_old所有变量的标签 labels_old <- sapply(df_old, attr, "label") # 循环赋值给df_new的对应列 for(j in seq_along(df_new)) { attr(df_new[[j]], "label") <- labels_old[j] }
方法2:用haven包的set_label函数(更直观)
如果使用haven包处理带标签的数据,可以直接用set_label函数批量设置:
library(haven) labels_old <- sapply(df_old, attr, "label") for(j in seq_along(df_new)) { df_new[[j]] <- set_label(df_new[[j]], labels_old[j]) }
方法3:purrr批量处理(简洁版)
借助purrr包的map2函数可以一行完成批量赋值:
library(purrr) library(dplyr) labels_old <- sapply(df_old, attr, "label") df_new <- map2(df_new, labels_old, function(col, lbl) { attr(col, "label") <- lbl col }) %>% bind_cols()
为什么原代码不生效?
原代码用df_new[,j]提取列时,返回的是向量的副本,修改副本的属性不会影响原dataframe中的列。而用df_new[[j]]是直接引用原dataframe中的列,修改属性会直接生效。
内容的提问来源于stack exchange,提问作者Shaun
相关产品推荐
相关产品推荐

