2017-03-01 75 views
1

我有一个简单的二进制结构,有几个重复的数据类型,我需要在R有效读取。例如,整数icount,后面是结构{a integer, b real},重复icount次。例如,考虑由Python编写的这个简单的文件: 在R读取二进制结构

# Python -- this is not my question, it just makes data for my question 
from struct import pack 
with open('foo.bin', 'wb') as fp: 
    icount = 123456 
    fp.write(pack('i', icount)) 
    for i in range(icount): 
     fp.write(pack('if', i, i * 100.0)) 

(你可以download this <1 MB file,如果你不希望产生的话)

要读取该文件到[R,我可以使用readBin在for循环,但它是痛苦慢(如预期):

# R 
fp <- file("foo.bin", "rb") 
icount <- readBin(fp, "integer", size=4) 
df <- data.frame(a=integer(icount), b=numeric(icount)) 
for (i in seq(icount)) { 
    df$a[i] <- readBin(fp, "integer", size=4) 
    df$b[i] <- readBin(fp, "numeric", size=4) 
} 
close(fp) 

我想知道一个更有效的方法来的将非均匀二进制结构读取为data.frame结构(或类似结构)。如果可能,我知道应始终避免使用for-loops。

+0

我还没有使用它,但'包:: unpack'宣称能够根据模板来解压原始载体。 – r2evans

+0

你能分享一下数据的样子吗? – TUSHAr

+0

@Tushar您可以生成它或[下载](http://filebin.ca/3E2SWO2QJvHu/foo.bin) –

回答

0

我发现了一个快速运行的解决方法,这是为了读出结构数据的整个块作为“原始”,然后切片的部件出来解释结构。让我证明:

fp <- file("foo.bin", "rb") 
icount <- readBin(fp, "integer", size=4) 
rec_size = 4 + 4 # int is 4 bytes + float is 4 bytes 
raw <- readBin(fp, "raw", n=icount * rec_size) 
close(fp) 

# Interpret raw bytes using specifically tailored slices for the structure 
raw_sel_a <- rep(0:icount, each=4) * rec_size + 1:4 
raw_sel_b <- rep(0:icount, each=4) * rec_size + 1:4 + 4 
df <- data.frame(
    a = readBin(raw[raw_sel_a], "integer", size=4, n=icount), 
    b = readBin(raw[raw_sel_b], "numeric", size=4, n=icount)) 

棘手的部分是制作raw_sel切片原料结构的相关部分阅读。这个例子很简单,因为每个数据成员都是4个字节。不过,我可以想象,对于复杂的数据结构来说这更难。

0

作为一个说明,你的循环了(只测试一次):

user system elapsed 
174.04 1.55 180.96 

我加快了读了使用:

fp <- file("foo.bin", "rb") 
icount <- readBin(fp, "integer", size=4) 
df <- data.frame(a=integer(icount), b=numeric(icount)) 
x=replicate(icount*2,readBin(fp, "integer", size=4)) 
x=x[0:(icount-1)*2+1] 
close(fp) 
fp <- file("foo.bin", "rb") 
y=replicate(icount*2+1,readBin(fp, "numeric", size=4)) 
y=y[1:(icount)*2+1] 
df$a=x 
df$b=y 
close(fp) 

这是速度比我预期:

user system elapsed 
3.08 0.10 3.18