2.4 直接使用 scan 函数
Next: Re-shaping data,Previous: Data Interchange Format (DIF),Up: Spreadsheet-like data
2.4 直接使用 scan 函数
read.table 和 read.fwf 都是先用 scan 读文件,然后处理 scan 的结果。它们非常便利,但有时直接使用 scan 效果会比较好。
函数 scan 有很多参数。大多数参数在函数 read.table 里面也存在。其中最为关键的参数是 what,它是用来指定从文件中读出的变量的模式(mode)的列表。如果该列表已经被命名,它的名字会被用作返回列表的分量。模式可以是数值,字符或复数,并且常常用例子来指定,比如0,"" 或 0i。例如,
cat("2 3 5 7", "11 13 17 19", file="ex.dat", sep="\n")
scan(file="ex.dat", what=list(x=0, y="", z=0), flush=TRUE)
返回一个有三个分量的列表并且丢弃文件中的第四列。
还有一个非常有用的函数readLines。如果你想把所有行读入 R 然后进一步处理,可以用这个便利的函数。
scan 的一个最普遍的应用是读入大的矩阵。假定文件matrix.dat 只是包括一个 200 x 2000的矩阵1,那么我们可用
A <- matrix(scan("matrix.dat", n = 200*2000), 200, 2000, byrow = TRUE)
在一个测试里面,这花费了1秒钟(在Linux系统测试的,同样电脑上在Windows系统下则需要3秒钟),而
A <- as.matrix(read.table("matrix.dat"))
花费了10秒钟(和更多的内存),另外,
A <- as.matrix(read.table("matrix.dat", header = FALSE, nrows = 200,
comment.char = "", colClasses = "numeric"))
花费了7秒钟。造成这种差别的原因差不多完全由于读2000分开的短列的时间开支所致:如果它们的长度是2000,scan花费9秒,而read.table 在比较高效地使用情况(特别是设定colClasses)下需要18秒;但缺乏技巧地使用read.table时则需要125秒!
注意,时限测试依赖于读的类型和数据本事。下面是一个读取一百万个不同整数的例子:
writeLines(as.character((1+1e6):2e6), "ints.dat")
xi <- scan("ints.dat", what=integer(0), n=1e6) # 0.77s
xn <- scan("ints.dat", what=numeric(0), n=1e6) # 0.93s
xc <- scan("ints.dat", what=character(0), n=1e6) # 0.85s
xf <- as.factor(xc) # 2.2s
DF <- read.table("ints.dat") # 4.5s
以及一百万个小集合代码的例子:
code <- c("LMH", "SJC", "CHCH", "SPC", "SOM")
writeLines(sample(code, 1e6, replace=TRUE), "code.dat")
y <- scan("code.dat", what=character(0), n=1e6) # 0.44s
yf <- as.factor(y) # 0.21s
DF <- read.table("code.dat") # 4.9s
DF <- read.table("code.dat", nrows=1e6) # 3.6s
注意,这些时限测试严重依赖操作系统(Windows下面的基本读取所花的时间至少是Linux系统下面的两倍)和垃圾收集器的精度。
Footnotes
[1] 译者注:可以利用命令生成随机矩阵,
write.table(matrix(rnorm(200*2000), 200), "matrix.dat", row.names=F, col.names=F)
Hits:Loading...
- Previous Page: 2.3 数据交换模式 (DIF)
- Next Page: 2.5 数据重塑
