Чтение текстового файла неправильного формата, состоящего из текста с/без пробелов и цифр

Образцы данных выглядят так (кстати, у меня есть сотни таких файлов). Сложная часть - это "NO RECORD" в файле. Я не пытался часы, чтобы получить его в R без каких-либо успехов

BEGIN DATA
RIM
DATE           AF         QD         QU 
09/30/1920      NO RECORD       370.00  NO RECORD   
10/01/1920      NO RECORD       391.00     391.00 
10/02/1920      NO RECORD       496.00    MISSING 
10/03/1920      NO RECORD       660.00    MISSING 
10/04/1920      NO RECORD       881.00    MISSING 
10/05/1920      NO RECORD       660.00    MISSING 
10/06/1920      NO RECORD       515.00    -9999 
10/07/1920      NO RECORD       443.00    NO RECORD 
10/08/1920      NO RECORD       443.00    MISSING 
10/09/1920      NO RECORD       443.00    443.00 
10/10/1920      NO RECORD       443.00    MISSING

Это мой последний код R

library(zoo)

# function to read data
obsRead <- function(path2file, filename, number_line_skip, header_or_not) {
  tmpName <- paste(path2file, filename, sep="")
  tmpData <- read.zoo(tmpName,
                   tz='', stringsAsFactors = FALSE, strip.white = TRUE,
                   header=header_or_not, skip=number_line_skip, 
                   na.strings = c("NA", "N/A", "MISSING", "NO RECORD", "-9999"), # tell zoo what NA values look like
  qName <- c("AF", "QD", "QU")
  names(tmpData) <- qName
  index(tmpData) <- as.Date(index(tmpData)) # Convert index from POSIXct to Date
  str(tmpData)
  return(tmpData)  
}

dataDir = "path/to/file/"
dataFile <- "sampleData.txt"
nLineSkip <- 3
header_or_not <- FALSE

Q_obs <- obsRead(dataDir, dataFile, nLineSkip, header_or_not)

И ошибка, которую я получил от R

Error in scan(file, what, nmax, sep, dec, quote, skip, nlines, na.strings,  : 
  line 2 did not have 6 elements

Любое предложение будет оценено! Спасибо!


person Tung    schedule 14.08.2014    source источник
comment
Так является ли фиксированная ширина данных (заголовки здесь кажутся немного неправильными)? Или, может быть, с разделителями табуляции?   -  person MrFlick    schedule 14.08.2014
comment
Случайный? Уверены ли вы? Кто бы создал такой формат? Вы действительно смотрели на байты файла? Вам лучше заменить все значения NO RECORD на NORECORD, прежде чем вы попытаетесь прочитать данные. Если вы используете Unix, вы можете передать его через sed. Или вы можете использовать readLines() в R, выполнить преобразование, а затем отправить в read.table. Но я не могу поверить, что в файле данных нет никакой логики.   -  person MrFlick    schedule 14.08.2014
comment
О, мой плохой. Извините за неправильное понимание вашего вопроса. Я только что проверил: столбец 1 имеет ширину 11, col. 2 имеет 15, цв. 3 имеет 13 и col.4 имеет 11. Спасибо также за предложение!   -  person Tung    schedule 14.08.2014
comment
read.fwf может помочь читать файлы фиксированной ширины.   -  person MrFlick    schedule 14.08.2014
comment
Еще раз спасибо @MrFlick!   -  person Tung    schedule 14.08.2014


Ответы (3)


При условии, что NO RECORD непротиворечиво, это должно дать вам начало:

tmp <- readLines("sample.dat")

# substitute 'NO RECORD' for 'NORECORD' and use read.table()
# to process the collapsed vector

tmp.collapse <- paste(gsub("NO RECORD", "NORECORD", 
                      tmp[4:length(tmp)]), sep="", collapse="\n")

# get the column names from the third row and use them in the data table

read.table(textConnection(tmp.collapse), 
           header=FALSE, stringsAsFactors=FALSE, 
           col.names=unlist(strsplit(tmp[3], "\ +")))

##          DATE       AF  QD       QU
## 1  09/30/1920 NORECORD 370 NORECORD
## 2  10/01/1920 NORECORD 391   391.00
## 3  10/02/1920 NORECORD 496  MISSING
## 4  10/03/1920 NORECORD 660  MISSING
## 5  10/04/1920 NORECORD 881  MISSING
## 6  10/05/1920 NORECORD 660  MISSING
## 7  10/06/1920 NORECORD 515    -9999
## 8  10/07/1920 NORECORD 443 NORECORD
## 9  10/08/1920 NORECORD 443  MISSING
## 10 10/09/1920 NORECORD 443   443.00
## 11 10/10/1920 NORECORD 443  MISSING
person hrbrmstr    schedule 14.08.2014
comment
Благодарю вас! Работает как шарм! Ваше здоровье - person Tung; 14.08.2014

Попробуй это:

library(zoo)
L <- readLines("path/to/file/sampleData.txt")
L <- gsub("NO RECORD", "NO_RECORD", L)
z <- read.zoo(text = L, header = TRUE, skip = 2, format = "%m/%d/%Y",
        na.strings = c("NA", "N/A", "MISSING", "NO_RECORD", "-9999"))
z

давая:

> z
           AF  QD  QU
1920-09-30 NA 370  NA
1920-10-01 NA 391 391
1920-10-02 NA 496  NA
1920-10-03 NA 660  NA
1920-10-04 NA 881  NA
1920-10-05 NA 660  NA
1920-10-06 NA 515  NA
1920-10-07 NA 443  NA
1920-10-08 NA 443  NA
1920-10-09 NA 443 443
1920-10-10 NA 443  NA
person G. Grothendieck    schedule 14.08.2014
comment
Спасибо @Г. Grothendieck за очень чистое решение! - person Tung; 15.08.2014

Расширяя комментарий @MrFlick, предполагающий, что sed, fread принимает системные команды напрямую:

fread("sed 's/NO RECORD/NORECORD/' < yourFile.txt")
person Matt Dowle    schedule 19.11.2014
comment
Спасибо, @Matt Dowle! Вот что я понял, почему я попробовал ваше предложение. Обратите внимание, что я использую GNU sed для Windows (sourceforge.net/projects/gnuwin32) › fread (sed 's/NO RECORD/NORECORD/' ‹ sample_data.txt) › Ошибка в fread(sed 's/NO RECORD/NORECORD/' ‹ sample_data.txt): › Неверное расположение после проверки формата строки заголовка. ch=' ' › Дополнительно: Предупреждающее сообщение: › In fread(sed 's/NO RECORD/NORECORD/' ‹ sample_data.txt): › Начало ввода данных в строке 3 и отбрасывание предыдущей непустой строки: 09/30/ 1920 НОРЕКОРД 370.00 НЕТ РЕКОРД - person Tung; 19.11.2014
comment
@thecatalyst Это похоже на отдельную проблему. Судя по сообщению об ошибке, это похоже на версию 1.9.5, но, пожалуйста, всегда указывайте. Затем нужно будет увидеть данные, желательно в виде файла в Dropbox или аналогичном. Пожалуйста, поднимите как вопрос, а не комментарии. Вы можете поместить ссылку на проблему в комментарий. - person Matt Dowle; 20.11.2014
comment
Спасибо, Мэтт! Я обновил его здесь github.com/Rdatatable/data.table/issues/964 - person Tung; 20.11.2014