如何在R中读取SAS生成的文本(.txt)文件并转为DataFrame?
在R中读取IBGE PENSE 2009的SAS生成文本文件为结构化DataFrame
核心思路
这个文本文件是固定宽度格式(SAS常用输出格式),核心是获取每个变量的名称、起止列位置和数据类型,再用R的固定宽度读取工具解析。
步骤1:获取变量布局信息
从压缩包的Documentação文件夹找到数据字典(通常是PDF或SAS程序文件),或者解析Input SAS文件夹里的控制文件,提取以下关键信息:
- 变量名
- 列的起始位置
- 列的结束位置(或宽度)
- 数据类型(字符型/数值型)
方法一:手动构建列规范(适合小量变量或精准控制场景)
用readr包的read_fwf()读取,先手动整理列规则:
# 加载依赖包 library(readr) library(dplyr) # 示例:根据数据字典构建列规范(替换为实际变量信息) col_spec <- tibble( col_name = c("ID_ALUNO", "IDADE", "SEXO", "ESCOLARIDADE"), start = c(1, 11, 13, 14), end = c(10, 12, 13, 16), col_type = c("c", "i", "i", "c") # c=字符型,i=整数型,n=数值型 ) # 读取固定宽度文本文件 pense_data <- read_fwf( file = "Dados/Base_Pense Completa_2009.txt", col_positions = fwf_positions( start = col_spec$start, end = col_spec$end, col_names = col_spec$col_name ), col_types = paste(col_spec$col_type, collapse = "") ) # 验证数据结构 glimpse(pense_data)
方法二:自动解析SAS输入控制文件(高效批量处理)
Input SAS文件夹里的.csv是SAS输入控制文件,包含变量位置定义,直接解析后读取:
library(readr) library(stringr) # 读取SAS输入控制文件(替换为实际文件名) sas_input <- read_csv("Input SAS/[控制文件名].csv", col_names = FALSE) # 解析控制文件,提取变量名、位置和类型 parsed_spec <- sas_input %>% mutate( col_name = str_extract(X1, "^\\w+"), # 提取变量名 position = str_extract(X1, "\\d+(-\\d+)?") # 提取位置信息(如1-10或10) ) %>% separate(position, into = c("start", "end"), sep = "-", fill = "right") %>% mutate( start = as.integer(start), # 处理宽度格式(如变量名 10 等价于start到start+9) end = ifelse(is.na(end), start + as.integer(str_extract(X1, "(?<=\\s)\\d+$")) - 1, as.integer(end)), col_type = ifelse(str_detect(X1, "\\$"), "c", "i") # 带$标记的是字符型 ) %>% filter(!is.na(col_name)) # 过滤无效行 # 读取数据 pense_data <- read_fwf( file = "Dados/Base_Pense Completa_2009.txt", col_positions = fwf_positions( start = parsed_spec$start, end = parsed_spec$end, col_names = parsed_spec$col_name ), col_types = paste(parsed_spec$col_type, collapse = "") )
后续优化
- 用
labelled包给变量添加语义标签(参考数据字典):library(labelled) var_labels(pense_data$IDADE) <- "Idade do aluno em anos" var_labels(pense_data$SEXO) <- "Sexo do aluno (1=Masculino, 2=Feminino)" - 处理缺失值:根据数据字典定义的缺失编码(如99、-9等)替换为
NA:pense_data <- pense_data %>% mutate(IDADE = na_if(IDADE, 99))
内容的提问来源于stack exchange,提问作者Lana Meijinhos
相关产品推荐
相关产品推荐

