在Tidyverse中移除指定变量标签/限制as_factor()的转换范围
解决英国选举研究(BES)数据标签转换与移除问题
我完全懂你处理BES数据时的困扰——从Stata的.dta文件导入后,haven包给变量加的标签大多时候有用,但碰到像age这种需要数值的变量时,as_factor()的全局转换就很碍事。下面针对你的问题一步步来解决:
1. 只对特定列使用as_factor()转换
其实不用让as_factor()处理整个数据框,结合dplyr的mutate()就能精准指定要转换的列。比如你只想把投票意向变量转成因子,而保留age的数值类型,代码可以这么写:
library(haven) library(dplyr) # 导入你提供的示例数据 bes_data <- structure(list(ageW19 = structure(c(72, 52, 39, 75, 26, 56), label = "Age", format.stata = "%8.0g", labels = c(`Not Asked` = -9, Skipped = -8), class = c("haven_labelled", "vctrs_vctr", "double" )), generalElectionVoteW19 = structure(c(1, 13, 3, 1, 2, 1), label = "General election vote intention (recalled vote in post-election waves)", format.stata = "%40.0g", labels = c(`I would/did not vote` = 0, Conservative = 1, Labour = 2, `Liberal Democrat` = 3, `Scottish National Party (SNP)` = 4, `Plaid Cymru` = 5, `United Kingdom Independence Party (UKIP)` = 6, `Green Party` = 7, `British National Party (BNP)` = 8, Other = 9, `Change UK- The Independent Group` = 11, `Brexit Party` = 12, `An independent candidate` = 13, `Don't know` = 9999), class = c("haven_labelled", "vctrs_vctr", "double"))), row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame"), na.action = c(`1` = 1L, `3` = 3L, `5` = 5L )) # 只转换投票意向列为因子,其他变量保持原样 bes_processed <- bes_data %>% mutate(generalElectionVoteW19 = as_factor(generalElectionVoteW19)) # 检查变量类型:ageW19仍是带标签的数值,投票意向是因子 str(bes_processed)
这样操作后,ageW19依然保持haven_labelled的数值类型,不会影响后续画图时的数值运算。
2. 移除特定变量的标签(避免数据类型改变)
你之前用sjlabelled时出现数据类型变化,是因为错误地用了str()包裹赋值——str()是用来查看结构的,不是用来保存数据的。正确的做法是直接把移除标签后的向量赋值回原数据框的列,或者用mutate()批量处理:
方法1:直接赋值单个变量
library(sjlabelled) # 移除ageW19的所有标签,保留数值类型 bes_data$ageW19 <- remove_all_labels(bes_data$ageW19)
方法2:用dplyr批量处理(适合多个变量)
bes_data <- bes_data %>% mutate( ageW19 = remove_all_labels(ageW19), # 如果还有其他要移除标签的变量,在这里添加 # another_var = remove_all_labels(another_var) )
这样处理后,ageW19会变成普通的double类型,完全可以用于直方图的数值映射,而且整个数据框的结构不会改变。
3. 针对你画图场景的完整解决方案
结合你要画“特定年龄下各政党得票人数直方图”的需求,这里给你一套完整的处理+画图代码:
library(haven) library(dplyr) library(ggplot2) # 处理数据:转换投票意向为因子,移除age的标签,过滤无效年龄值 bes_ready <- bes_data %>% mutate( generalElectionVoteW19 = as_factor(generalElectionVoteW19), ageW19 = remove_all_labels(ageW19) ) %>% filter(ageW19 >= 18) # 过滤掉未作答/跳过的无效年龄 # 绘制分组直方图 ggplot(bes_ready, aes(x = ageW19, fill = generalElectionVoteW19)) + geom_histogram(binwidth = 5, position = "dodge", alpha = 0.8) + labs( title = "各政党得票人数的年龄分布", x = "年龄", y = "人数", fill = "投票意向" ) + theme_minimal()
这样既保留了投票意向的因子标签(画图时自动显示政党名称),又让age变量恢复成纯数值,完美解决画图出错的问题,比最后再转数值要高效得多。
内容的提问来源于stack exchange,提问作者jolene
相关产品推荐
相关产品推荐

