我是否正确地假设使用压缩文件这是不可能的,仅仅是因为 gzip 需要从一开始就解压缩所有内容?
事实上,为了简短的解释,让我们以一些虚拟方法作为起点:
AAAAVVBABBBC
gzip 会做类似的事情:4A2VBA3BC
显然,您无法A
在不阅读所有文件的情况下从文件中提取所有内容,因为您无法猜测是否有A
结尾。
对于另一个问题“加载保存的文件的一部分”,我看不到解决方案。您可能可以使用write.csv
和read.csv
(或fwrite
从fread
包中data.table
)使用skip
和nrows
参数可能是另一种选择。
无论如何,在已读取的文件上使用任何函数都意味着在过滤之前将整个文件加载到内存中,这比读取文件然后从内存中进行子集化没有更多的时间。
您可以在 Rcpp 中制作一些东西,利用流来读取数据而不将它们加载到内存中,但是在决定是否应该保留之前读取和解析每个条目不会给您带来真正更好的吞吐量。
saveDRS
将保存数据的序列化版本,例如:
> myvector <- c("1","2","3").
> serialize(myvector,NULL)
[1] 58 0a 00 00 00 02 00 03 02 03 00 02 03 00 00 00 00 10 00 00 00 03 00 04 00 09 00 00 00 01 31 00 04 00 09 00 00 00 01 32 00 04 00 09 00 00
[47] 00 01 33
它当然是可解析的,但意味着根据格式读取每个字节的字节。
另一方面,您可以编写为 csv(或write.table
更复杂的数据)并在阅读之前使用外部工具,大致如下:
z <- tempfile()
write.table(df, z, row.names = FALSE)
shortdf <- read.table(text= system( command = paste0( "awk 'NR > 5 && NR < 10 { print }'" ,z) ) )
您将需要一个带有awk的 linux 系统,它能够在几毫秒内解析数百万行,或者显然可以使用 Windows 编译版本的awk 。
主要优点是awk能够过滤每行数据的正则表达式或其他一些条件。
作为data.frame的补充,data.frame或多或少是一个向量列表(简单的例子),这个列表将被顺序保存,所以如果我们有一个像这样的数据框:
> str(ex)
'data.frame': 3 obs. of 2 variables:
$ a: chr "one" "five" "Whatever"
$ b: num 1 2 3
它的序列化是:
> serialize(ex,NULL)
[1] 58 0a 00 00 00 02 00 03 02 03 00 02 03 00 00 00 03 13 00 00 00 02 00 00 00 10 00 00 00 03 00 04 00 09 00 00 00 03 6f 6e 65 00 04 00 09 00
[47] 00 00 04 66 69 76 65 00 04 00 09 00 00 00 08 57 68 61 74 65 76 65 72 00 00 00 0e 00 00 00 03 3f f0 00 00 00 00 00 00 40 00 00 00 00 00 00
[93] 00 40 08 00 00 00 00 00 00 00 00 04 02 00 00 00 01 00 04 00 09 00 00 00 05 6e 61 6d 65 73 00 00 00 10 00 00 00 02 00 04 00 09 00 00 00 01
[139] 61 00 04 00 09 00 00 00 01 62 00 00 04 02 00 00 00 01 00 04 00 09 00 00 00 09 72 6f 77 2e 6e 61 6d 65 73 00 00 00 0d 00 00 00 02 80 00 00
[185] 00 ff ff ff fd 00 00 04 02 00 00 00 01 00 04 00 09 00 00 00 05 63 6c 61 73 73 00 00 00 10 00 00 00 01 00 04 00 09 00 00 00 0a 64 61 74 61
[231] 2e 66 72 61 6d 65 00 00 00 fe
翻译成ascii的一个想法:
X
one five Whatever?ð@@ names a b row.names
ÿÿÿý class
data.frameþ
我们有文件的标题,列表的标题,然后是组成列表的每个向量,因为我们不知道字符向量将占用多少大小,所以我们不能跳到任意数据,我们必须解析每个标头(文本数据之前的字节给出它的长度)。更糟糕的是,现在要获得相应的整数,我们必须去整数向量头,如果不解析每个字符头并将它们相加,就无法确定。
所以在我看来,制作一些东西是可能的,但可能不会比读取所有对象快得多,而且保存格式会很脆弱(因为 R 已经有 3 种格式来保存对象)。
这里有一些参考
与 ascii 格式的序列化输出相同的视图(更易读以了解其组织方式):
> write(rawToChar(serialize(ex,NULL,ascii=TRUE)),"")
A
2
197123
131840
787
2
16
3
262153
3
one
262153
4
five
262153
8
Whatever
14
3
1
2
3
1026
1
262153
5
names
16
2
262153
1
a
262153
1
b
1026
1
262153
9
row.names
13
2
NA
-3
1026
1
262153
5
class
16
1
262153
10
data.frame
254