8.3 魔鬼(no.1~no.10)
最最凶残的问题就是正确地在R中读取文件中的数据。
8.3.1 read.table
函数read.table
是R获得数据最常用的方法。如果你用到read.table
,将它的帮助文档阅读三次将是非常有效的时间安排。尤其是header
和row.names
两个参数应该被视为列名和行名。
另外一个伟大的时间管理工具是在你尝试使用这些数据时对数据的结果进行检查。
8.3.2 读一个表
函数read.table
不会常见一张表—它会创建一个数据框。你不会仅仅读了一本书就会变成一本书吧。函数table返回一个表。
read.table
和相关函数的思想是它们读取的数据都是矩阵的格式。
8.3.3 the missing, the whole missing and nothing but the missing(翻译不了)
错误地读入缺失值是一个高效的产生垃圾的方式。缺失值可以变为非缺失的,非缺失的可以变成确实值,逻辑数值可以变为因子。
read.table
中的参数na.strings需要合理地设置。一个例子或许可以是这样的:
na.strings=c(’.’, ’-999’)
8.3.4 错误的引号
一个相当常见的文件格式是一个列名后边含有一些数据。如果有任何的撇号在这些名字中,那么除非你在read.table
中设置了参数quote
否则你很有可能得到一个错误。一个可能的设置是:
quote=’’
听起来像是非常简单的建议,但是几乎可以肯定的是当引号是个问题是往往是不明显的。你会得到这样的错误:在一行中有错误数量的条目。当你得到这样的错误,使用count.fields
来查看R
是怎样思考你的数据的是一个非常好的想法。
一行中的一些信息:
foo.cf <- count.fields(’foo.txt’, sep=’\t’)
table(foo.cf)
8.3.5 thymine(胸腺嘧啶) 是 TRUE, female(女性) is FALSE
当你在读取DNA数据时,基于被命名的A,T,G和C。列被以factors
的形式读取。除了这个列都是T—这个列是逻辑的。
相似地,一个性别列的数据全是F—这个列是逻辑的。
解决方案是使用read.table
中的参数:
colClasses=’character’
或者
colClasses=’factor’
看你喜欢哪个了。
如果有其他类型的列,那么你需要对文件的列提出一个合适的类型的向量给colClasses
。
使用colClasses
也可以是调用更加有效。
8.3.6 空格是白的
空格是看不见的,我们总是预测看不见的就意味着不存在。
> factor(c(’A ’, ’A’, ’B’))
[1] A A B
Levels: A A B
在读取数据时,非常容易得到类似的因子。可以通过设置read.table
中的参数strip.white
为TRUE
来阻止这个。
8.3.7 额外领域
当一个文件是电子表格的时候,有时会有额外的空值在文件的某些行。这种情况下你或许会获得类似的错误:
> mydat <- read.table(’myfile’, header=TRUE, sep=’\t’)
Error in scan(file, what, nmax, sep, dec, quote, skip, :line 10 did not have 55 elements
这个,当然,是一个使用count.fields
来看发生了什么的绝佳情况。如果额外的空领域确实是问题的来源,那么解决方案是:
> mydat <- read.table(’myfile’, header=TRUE, sep=’\t’,fill=TRUE)
> mydat <- mydat[, 1:53]
在这个节点上,聪明的选择是仔细地审查数据以确定是否被正确地读进来并且是对齐的。
8.3.8 fill
和额外领域
当参数fill
是TRUE
(在read.csv
和read.delim
的默认值是这样,但是在read.table
不是),如果有数量变化的领域在文件中会造成问题。
> writeLines(c("A,B,C,D",
+ "1,a,b,c",
+ "2,d,e,f",
+ "3,a,i,j",
+ "4,a,b,c",
+ "5,d,e,f",
+ "6,g,h,i,j,k,l,m,n"),
+ con=file("test.csv"))
> read.csv("test.csv")
A B C D
1 1 a b c
2 2 d e f
3 3 a i j
4 4 a b c
5 5 d e f
6 6 g h i
7 j k l m
8 n
> read.csv("test.csv", fill=FALSE)
Error in scan(file = file, what = what, ... :
line 6 did not have 4 elements
文件的前5行检查了领域数量的一致性。使用count.fields
来检查整个文件。
8.3.9 读入混乱的文件
read.table
和它的相关函数被设计用来读取那些表格式的文件。并不是所有文件都是这种格式。尝试使用read.table
或者它的相关函数读取一个非表格式的文件是愚蠢的—当遇到损坏的数据你可以结束了。
有两个使用更加广泛的函数scan
和readLines
。
8.3.10 不完美的写出与读入
不要认为将一个数据写入一个文件(比如write.table
),然后将这个数据读入R
,它们会精确地相同。这是在做两个转换,转换过程中经常会有一些东西丢失。
你有一些选择得到你想要的:
- 使用
save
存储对象并且使用attach
或者load
使用它。这个对于多个对象适用。 - 使用
dput
写一个关于对象的ASCII 表达式并且使用dget
将其带回R
。 - 使用
serialize
写并且使用unserialize
进行读。(但是帮助文件警告格式可能会改变。)