R批量转换数据集值标签重音字符编码并写回原数据的方法
批量修复Stata导入值标签编码问题
问题描述
导入包含重音字符的Stata文件时出现编码异常,单变量转码可修复labelled包look_for()函数的报错,但缺少批量处理全数据集值标签编码、将转码结果写回原数据的方法。
报错复现
加载数据并调用look_for()时触发多字节字符串错误:
remotes::install_github("sjkiss/cesdata") library(cesdata) data("ces19web") library(labelled) look_for(ces19web, "vote")
报错信息:
Error in structure(as.character(x), names = names(x)) :
invalid multibyte string at 'bec Solidaire'
问题定位
经排查,错误根源是变量值标签为latin1编码,未正确转换为UTF-8:
- 选择前12个变量调用
look_for()可正常运行 - 选择包含第13个变量的前13列时函数运行失败
排查代码:
# 可正常运行 ces19web %>% select(1:12) %>% look_for(., "[a-z]") # 运行报错 ces19web %>% select(1:13) %>% look_for(., "[a-z]") # 查看含重音字符的值标签 val_labels(ces19web[,13])
单变量修复验证
对单个存在问题的变量,将值标签名称从latin1转码为UTF-8即可解决报错,代码如下:
names(val_labels(ces19web$cps19_imp_iss_party))<-iconv(names(val_labels(ces19web$cps19_imp_iss_party)), from="latin1", to="UTF-8")
处理后前13列调用look_for()可正常运行。
现有尝试
已通过map函数遍历所有变量完成值标签转码,可得到正确的转码结果列表,但无法将结果写回原数据集替换原有问题标签,尝试代码如下:
ces19web %>% # 遍历所有变量提取值标签 map(., val_labels) %>% # 遍历每一组值标签 map(., ~{ # 无值标签则跳过 if (!is.null(.x)){ # 存在值标签则将名称从latin1转码为UTF-8 names(.x)<-iconv(names(.x), from="latin1", to="UTF-8") } }) ->out # 对比原数据第16个变量的值标签 ces19web[,16] # 和转码后输出的第16组值标签 out[[16]]
批量修复方案
使用imap逐列处理变量,转码值标签后直接赋值回对应列,最后将结果转回数据框格式即可,代码如下:
library(tidyverse) library(labelled) ces19web <- ces19web %>% imap(~{ # 提取当前列的值标签 col_labels <- val_labels(.x) # 存在值标签则执行转码 if (!is.null(col_labels)) { names(col_labels) <- iconv(names(col_labels), from = "latin1", to = "UTF-8") # 将转码后的值标签写回当前列 val_labels(.x) <- col_labels } # 如果变量标签也存在编码问题,可取消以下注释同步修复 # col_var_label <- var_label(.x) # if (!is.null(col_var_label)) { # var_label(.x) <- iconv(col_var_label, from = "latin1", to = "UTF-8") # } return(.x) }) %>% as_tibble()
处理完成后全量数据集调用look_for()将不再触发编码报错。
内容的提问来源于stack exchange,提问作者spindoctor
相关产品推荐
相关产品推荐

