我说得对不对的假设,这将是不可能的压缩文件 ,只是因为需要的gzip解压缩一切从 开始?
事实上,对于一个简短的说明,让我们一些虚拟的方法为出发点:
AAAAVVBABBBC
的gzip会做这样的事情:4A2VBA3BC
显然,你不能提取该文件中的所有A
不读书它是否有一个A
在年底或不是所有的,因为你不能猜测。
对于其他问题“已保存的文件的加载部分”我不能看到我的头顶上有一个解决方案。您可以使用write.csv
和read.csv
(或fwrite
和fread
来自data.table
包),其中skip
和nrows
参数可以是替代参数。
通过一切手段,使用上已经阅读将意味着加载在内存中的整个文件过滤,这是不超过读取文件,然后从内存子集化更多的时间之前文件中的任何功能。
您可以在Rcpp中创建一些内容,利用流读取数据而不将它们加载到内存中,但是在决定它是否应该保留之前阅读和解析每个条目将不会提供真正的更好的吞吐量。
saveDRS
将保存DATAS的序列化版本,例如:
> 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)))
你需要用linux系统awk它能够在几毫秒内解析数百万行,或者显然使用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种格式来保存对象)。
Some reference here
相同的视图,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
*“,但阅读并决定是否应保持之前解析每个条目否则不会给你一个真正的更好的吞吐量。“*没有必要读一切。 'fseek'可以在一段时间内跳过任意大小的数据。真正的问题是格式是否让我们知道我们希望忽略的子数据结构的确切大小(在磁盘上)。 –
@AaronMcDaid不是,格式是连续的。读取data.frame或多或少读取一个列表,代码是[here](https://github.com/wch/r-source/blob/73e11b7c40d3630604855e8eee3d1f309e2c9a57/src/main/serialize.c#L1611-L1645)如果你想知道我的意思。简而言之,我的意思是说你不能真的'跳过'N行,因为你必须为每一行做多个fseeks。我会在答案中加入一些细节。 – Tensibai
感谢您的澄清。我会再次读你的答案。实际上,我刚写完自己的代码来解决这个问题,将data.frame的列存储在一系列'bigmemory'对象中[(CRAN上的bigmemory)](https://cran.r-project.org /web/packages/bigmemory/index.html)。这允许任意查找任何行。我必须注意以特殊方式存储'人物'矢量,但现在它正在工作。 –