【问题标题】:Data table from raw text file: number of columns vary原始文本文件中的数据表:列数不同
【发布时间】:2018-03-17 15:12:28
【问题描述】:

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

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

================================================ =========================版本

研究变量:发布版本号

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

注意事项: ------ 此变量在数据中显示为: ANES_cdf_VERSION:YYYY-mmm-DD 其中 mmm 是标准的 3 字符月份缩写(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)。

类型: ----- 字符 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,使用找到的最大变量数,但对于大文件可能会很慢。

感谢您的帮助。任何 cmets 表示赞赏。 这是所有代码:

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]

【问题讨论】:

    标签: r parsing


    【解决方案1】:

    有一种方便的替代方法可以读取这样的文件: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("[=]+", "\n\nid:") %>% 
          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
    

    【讨论】:

    • 谢谢!这确实有效!我不得不说原始数据有一些观察值的多行值,比如 NOTES,所以我必须先将它们折叠成一行。只更改了几行代码并使用了 read.dcf。
    • 非常好,非常感谢您的反馈!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-11
    • 2012-06-18
    相关资源
    最近更新 更多