如何将半结构化TXT代码书转换为R语言Data Frame?
半结构化代码书转Data Frame解决方案
问题背景
我有一个作为大型数据集代码书的半结构化.txt文件,结构示例如下:
============================== VAR V960922 NUMERIC Admin.48 SUMMARY - POST MODE ASSIGNMENT AND ADMINISTRATION ----------------------------------------------------------- Post mode in this variable refers to beginning mode (question Admin.47). 749 1. Assigned to personal, administered as personal IW 7 2. Assigned to personal, administered as telephone IW 28 3. Assigned to telephone, administered as personal IW 750 4. Assigned to telephone, administered as telephone IW 0. Inap, no Post IW ==============================
希望将该结构转换为Data Frame用于后续数据清洗与标注,理想输出格式如下:
| Var Name | Frequencies | Value Labels | -------- | ----------- | --------------------------------------------------- | V960922 | 749 | 1. Assigned to personal, administered as personal IW | V960922 | 7 | 2. Assigned to personal, administered as telephone IW | V960922 | 28 | 3. Assigned to telephone, administered as personal IW | V960922 | 750 | 4. Assigned to telephone, administered as telephone IW | V960922 | NA | 0. Inap, no Post IW
文件中各变量结构类似,但值数量、摘要长度有差异。
我目前用readLines读取文件,通过str_subset提取行来拼接Data Frame:
nes <- readLines("nes1996var.txt") vars <- str_subset(nes, "^VAR") vars numbers <- str_subset(nes,"\\d?\\.") numbers
提取变量名成功,但提取表格时遇到困难:行首空白导致无法按行首数字筛选;用"数字+句号"筛选会误捕无关内容,且多行标签会被截断;还无法分离同一行的频率与标签。
可行解决方案
经调整后,以下方案可实现需求:
rl <- readLines("你的txt文件路径") ## 去除每行首尾的空白字符 ## 这样频率值会成为对应行的起始内容 rl <- trimws(rl) ## 定位分隔变量的分隔符行 delims <- grep("==============================", rl) ## 初始化输出列表 out <- vector(mode="list", length=length(delims)-1) ## 遍历每个变量块 for (i in 1:(length(delims) - 1)) { ## 提取相邻分隔符之间的内容作为单个变量的信息 vbl <- rl[(delims[i] + 1):(delims[(i + 1)] - 1)] ## 从第一行提取变量名(截取"VAR "之后的内容) varname <- gsub("VAR (.*)", "\\1", vbl[1]) ## 定位以数字开头的行(对应频率和标签的起始行) resps <- grep("^\\d", vbl) if (length(resps) > 0) { ## 找到最后一个响应行之后最近的空白行,作为最后一个响应类别的结束标记 blanks <- which(vbl == "") resps <- c(resps, blanks[min(which(blanks > max(resps)))]) ## 提取频率值,移除最后一个空白行对应的无效值 freqs <- gsub("^(\\d+).*", "\\1", vbl[resps]) freqs <- freqs[-length(freqs)] ## 拼接每个响应类别的多行标签内容 vlabs <- sapply(1:(length(resps) - 1), function(j) { paste(vbl[resps[j]:(resps[(j + 1)] - 1)], collapse = " ") }) ## 移除标签开头的频率值和空白字符,并清理标签首尾空白 vlabs <- trimws(gsub("^\\d+\\s+(.*)", "\\1", vlabs)) ## 将变量名、频率、标签整合为Data Frame out[[i]] <- data.frame(`Var Name` = varname, Frequencies = freqs, `Value Labels` = vlabs) } else { ## 无响应行时生成空Data Frame out[[i]] <- data.frame(`Var Name` = character(0), Frequencies = character(0), `Value Labels` = character(0)) } } ## 最后将所有变量的Data Frame合并为一个大表 final_df <- do.call(rbind, out)
注意:代码中需将"你的txt文件路径"替换为实际文件路径;最后一行的合并操作可根据需求选择是否执行。
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

