Чтение данных фиксированной ширины без перевода строки - PullRequest
2 голосов
/ 27 февраля 2012

У меня плоский файл фиксированной ширины без перевода строки и перевода строки (дамп из AS400).

Как загрузить этот файл в R data.frame?

Я пробовал разные комбинации textConnection и read.fwf, но безрезультатно.

Приведенный ниже код вызывает сбой Rstudio, поэтому я предполагаю, что перегружаю систему.

len ниже - 24376400, что является ручным, поскольку файлы, которые я обычно загружаю с использованием read.table. Длина записи составляет 400.

Есть ли какой-либо параметр RECLEN, который я должен установить, аналогичный SAS? Есть ли возможность установить EOL = "\ n" или "\ r \ n"? Спасибо.

fname <- "AS400FILE.TXT"
len <- file.info(fname)$size
conn <- file(fname, 'r')
contents <- readChar(conn, len)
close(conn)

df <- read.fwf( textConnection(contents) , widths=layout$length , sep="")

> dput(layout)
structure(list(start = c(1L, 41L, 81L, 121L, 161L, 201L, 224L, 
226L, 231L, 235L, 237L, 238L, 240L, 280L, 290L, 300L, 305L, 308L, 
309L, 330L, 335L, 337L, 349L, 350L, 351L, 355L, 365L), end = c(40L, 
80L, 120L, 160L, 200L, 223L, 225L, 230L, 234L, 236L, 237L, 239L, 
279L, 289L, 299L, 304L, 307L, 308L, 329L, 334L, 336L, 348L, 349L, 
350L, 354L, 364L, 400L), length = c(40L, 40L, 40L, 40L, 40L, 
23L, 2L, 5L, 4L, 2L, 1L, 2L, 40L, 10L, 10L, 5L, 3L, 1L, 21L, 
5L, 2L, 12L, 1L, 1L, 4L, 10L, 36L), label = c("TITLE", "SUFFIX", 
"ADDRESS1", "ADDRESS2", "ADDRESS3", "CITY", "STATE", 
"ZIP", "ZIP+4", "DELIVERY", "CHECKD", "FILLER", "NAME", 
"SOURCECODE", "ID", "FILLER", "BATCH", "FILLER", "FILLER", 
"GRID", "LOT", "FILLER", "CONTROL", 
"ZIPIND", "TROUTE", "SOURCEA", "FILLER")), .Names = c("start", 
"end", "length", "label"), class = "data.frame", row.names = c(NA, 
-27L))
> dim(layout)
[1] 27  4
> 

1 Ответ

3 голосов
/ 27 февраля 2012

Вы могли бы использовать readChar для этого.

Сначала составьте некоторые примерные данные (я думаю, что формат, как вы описываете, насколько я могу судить по вопросу? Т.е. стена текста с указаннымширина на столбец, нет новых строк во всем файле):

lengths <- c(2,3,4,2,3,4)
nFields <- length(lengths)
nRows   <- 10              # let's make 10 rows.
contents <- paste(letters[sample.int(26,size=sum(lengths)*nRows,replace=TRUE)],
                  collapse="")
#> contents
#[1] "lepajmcgcqooekmedjprkmmicm.......
cat(contents,file='test.txt')

Я могу придумать 3 способа сделать это, различные различия между каждым:

Если вы знаете количество строкзаранее вы можете сделать:

# If you know #rows in advance..
conn <- file('test.txt','r')
data <- readChar( conn, rep(lengths,nRows) )
close(conn)
# reshape data to dataframe
df <- data.frame(matrix(data,ncol=nFields,byrow=T))

В противном случае вы можете использовать цикл (зачем читать файл один раз для определения количества строк, а затем снова для анализа?)

# Otherwise use a loop
conn <- file('test.txt','r')
df <- data.frame(matrix(nrow=0,ncol=6)) # initialise 0-row data frame
while ( length(data <- readChar(conn, lengths)) > 0 ) {
    df[nrow(df)+1,] <- data
}
close(conn)

Или, поскольку у вас уже есть все contents в строке, вы можете просто разбить строку, используя substring:

# have already read in contents so can calculate nRows
nRows <- floor(nchar(contents)/sum(lengths)) # 10 for my example
starts <- c(0,cumsum(lengths[-nFields]))
df3 <- data.frame(t(
                    vapply( seq(1,nRows*sum(lengths),sum(lengths)),
                    function(r) 
                        substring(contents,starts+r,starts+r+lengths-1),
                    rep("",nFields) )))

Если вы хотите сделать это как можно меньшим чтением файла,Я предлагаю второй или третий методы.

Третий метод мне кажется наиболее элегантным, но требует, чтобы вы прочитали все contents сразу, что, в зависимости от размера файла, может не соответствоватьжизнеспособным.

Если это так, я бы пошел на второй, который читает только водин набор nFields полей за раз.

Я не рекомендую первое, , если только вы не знаете заранее количество строк - это была только моя первая попытка.Я не рекомендую это делать, потому что сначала вам нужно прочитать в файле , чтобы определить количество строк, а затем закрыть его и снова прочитать в .Если вы хотите пойти по этому пути, используйте метод 3!Однако, если вы заранее знаете количество строк, то можете использовать этот метод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...