2012-02-27 63 views
3

我有一個flatfile,固定寬度既沒有換行也沒有換行(從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 
> 
+0

你可以給你的文本文件的一小段嗎?我注意到你有'sep =「」' - 所以它是(例如)原始數據'08091011',寬度2 - >'08','09','10','11'?什麼是'layout $ length'?矢量?整數? – 2012-02-27 03:00:20

+0

佈局是具有字段名稱和字段寬度的數據幀: – 2012-02-27 03:02:42

+0

該文本文件是具有路由信息的名稱和地址數據:共有27個字段。佈局變量是包含字段$ length的數據框。 – 2012-02-27 03:09:05

回答

3

您可以使用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)) 

Otherwi本身你可以使用一個循環(爲什麼在文件中讀取一次制定的行數,然後再解析?)

# 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吧!但是,如果您事先知道其他方法的行數,則可以使用此方法。

+1

指出readChar的正確用法(使用rep(長度,nRows)而不是文件長度)確實有幫助。我沒有看這個正確的方法。謝謝你的幫助。 – 2012-02-27 11:42:58

+1

更新:上面建議的方法確實有效。隨着文件大小的增長,處理時間變得很快不切實際。我將使用> fold -400 AS400DATA.TXT |等等......之前加載R.謝謝。 – 2012-02-27 16:15:40