r - 原始文本文件中的数据表:列数各不相同



我有一个以下格式的原始文本文件:

发布版本:20150514(2015 年 5 月 14 日)

====

============================================================================== 版本研究变量:版本号

问题: 累积数据文件的---------版本

笔记: ------ 此变量在数据中显示为: ANES_cdf_VERSION:YYYY-mmm-DD,其中 mmm 是标准的 3 个字符的月份缩写(1 月 2 月 3 月 4 月 5 月 6 月 7 月 8 月 9 月 10 月 11 月 12 月)。

类型: -----角色-1

====

============================================================================== VCF0004研究变量:学习年份

问题: --------- 学习年份(4位数)

类型: ----- 数字 12 月 0-1

===========================================================================VCF0006 ... 等等

观测值以"="行为界,每个观测值都有一定数量的变量(并非所有变量都可能显示)

我正在尝试从中创建数据表。

我创建了一个观测向量,在每个观测列中用"|"分隔。然后我用fread做一个数据表:

dt <- fread(paste(rawObs, collapse = 'n'),sep = '|',header = F, fill = T)

但是,这并不是真正的解决方案。Fill = T 仅考虑观测值末尾的缺失列,而不考虑介于两者之间的列:

在示例中,我们得到它应该是:

id      | study_var | question | notes    | type
version | s1        | q1       | notes1   | character-1
VCF0004 | s2        | q2       | NA       | numeric

但 R 将其创建为

id      | study_var | question | notes    | type
version | s1        | q1       | notes1   | character-1
VCF0004 | s2        | q2       | numeric  | NA

第二个观测值的类型向左移动。作为一种解决方案,我正在考虑确定每个观察中缺少的列,并使用找到的最大变量数在输入文件中显式插入 NA,但对于大文件来说可能会很慢。

感谢您的帮助。任何意见不胜感激。 以下是所有代码:

library(magrittr)
library(data.table)
path <- 'Downloads/anes_timeseries_cdf_codebook_var.txt'
raw_data <- readLines(path)
head(raw_data)
#remove empty lines
raw_data <- raw_data[raw_data != ""]
#remove header
raw_data <- raw_data[-c(1,2)]
data_entries_index <-  grep('^=+', raw_data)+1
#add end position of the last observation
data_entries_index <- c(data_entries_index, length(raw_data))
#opening file shows editor couldn't read two characters - we can ignore it though
data_entries_index
parseRawObservation <- function(singleRawObs, VariableIndex){
count=length(VariableIndex)-1
for (i in 1:count){
start = VariableIndex[i]+2
end = VariableIndex[i+1]-1
varValue <- paste(singleRawObs[start:end],collapse = ' ')
if (i==1)
obsSpaced <- varValue
else
obsSpaced <- paste(obsSpaced,varValue, sep = '|')
}
obsSpaced
}

#create a vector of raw observations
numObs <- length(data_entries_index)
count=numObs-1
rawObs=vector()
for (i in 1:count) {
start <- data_entries_index[i]
end <- data_entries_index[i+1]-2
singleRawObs <-raw_data[start:end]
VariableIndex <- grep("^-+",singleRawObs)-1
#add end of the last variable index
VariableIndex <- c(VariableIndex, length(singleRawObs)+1)
rawObs[i] <- parseRawObservation(singleRawObs,VariableIndex) 
#add first two columns separately as they do not have dashes at the next line
rawObs[i] <- paste(singleRawObs[1], singleRawObs[2], rawObs[i], sep = '|')
}

#determine max number of fields
numOfCol <- max(sapply(rawObs,  FUN =  function(x) length(strsplit(x,'|')[[1]])))
which.max(sapply(rawObs,  FUN =  function(x) length(strsplit(x,'|')[[1]])))
dt <- fread(textConnection(rawObs),sep = '|',header = F)
dt <- fread(paste(rawObs[1:2], collapse = 'n'),sep = '|',header = F, fill = T)
rawObs[653]

读取这样的文件有一个方便的替代方法:read.dcf()

read.dcf()读取 Debian 控制格式 (DCF) 中的文件,该文件由常规的表单行tag:value组成。记录由一个或多个空行分隔。

但是,需要修改输入文件以符合 DCF 格式(加上一些额外的修改以满足 OP 的预期结果):

  1. 需要删除空行,因为它们会被误认为是记录分隔符。
  2. 用作记录分隔符的等号=的条纹需要替换为多个空行,并且缺少的标记id:
  3. 应删除破折号条纹。
  4. 应删除包含RELEASE VERSION:的第一行,以符合OP的期望。

下面的代码假定原始文本文件名为"raw.txt"

library(data.table)
library(magrittr)
# read raw file, skip first row
raw <- fread("raw.txt", sep = "n", header = FALSE, skip = 1L)
# replace streaks of "=" and "-"
raw[, V1 := V1 %>% 
stringr::str_replace("[=]+", "nnid:") %>% 
stringr::str_replace(": [-]+", ": ")][]
# now read the modified data using DCF format skipping empty rows
dt <- as.data.table(read.dcf(textConnection(raw[V1 != "", V1])))
dt
id            STUDY VARIABLE                        QUESTION
1: VERSION Version Number Of Release Version of Cumulative Data File
2: VCF0004             Year of Study         Year of study (4-digit)
3: VCF0006                        NA                              NA
                                                                                                  NOTES
1: This variable appears in the data as: ANES_cdf_VERSION:YYYY-mmm-DD [...]
2:                                                                                                                                                                         NA
3:                                                                                                                                                                         NA
TYPE
1:     Character-1
2: Numeric Dec 0-1
3:              NA

最新更新