• R语言
  • numeric被理解成character

我发现R在读取数据的时候,235,370,150 #注意数据列没有引号

这样的数据列,R会自动将它自动读成character,即使你colClasses="numeric" 来进行指定也不行,它还会报错,

Error in scan(file, what, nmax, sep, dec, quote, skip, nlines, na.strings, :

scan() expected 'a real', got '235,370,150'

请问如何处理?我怎样让它就是numeric?

发现一个秘密,R居然不使用千分位符号,请看

> a=123,456

Error: unexpected ',' in "a=123,"

我的本意是让a=123456,只不过加一个千分位符号罢了,不行。

发现一个秘密,R居然不使用千分位符号,请看

> a=123,456

Error: unexpected ',' in "a=123,"

我的本意是让a=123456,只不过加一个千分位符号罢了,不行。

回复 第4楼 的 kuanguang:“千分号符”是给人看的,又不是给机器看的。加上个逗号,机器当然看不懂这是个数字。

不支持是正常的,支持才是不正常的。问题的根源在于逗号的多义性,也就涉及到 CSV 格式本身的设计缺陷。如果要正确地用 CSV 格式保存这样的数据,就必须在字段的开始和结束加引号。关于这一点,在《Unix 编程艺术》中有过经典的讨论,摘录如下:

5.2.1 DSV 风格

DSV 代表 “Delimiter-Separated Values (分隔符分隔值)”。我们在文本元格式引用的第一个例子 /etc/passwd 文件就是一个使用冒号作为值分隔符的 DSV 格式。在 Unix 中,对字段值可能包含空格的 DSV 格式,冒号是默认的分隔符。

/etc/passwd 格式(每个记录一行,字段用冒号分隔)是 Unix 中非常传统的格式,经常用于处理表列数据。其它经典的例子包括描述安全组的 /etc/group 文件和在操作系统不同运行级别中控制 Unix 服务程序启动和关闭的 /etc/inittab 文件。

这种风格的数据文件一般应通过反斜杠(\)转义符支持在数据域中包含冒号。更为普遍的是,读取这种文件的代码可通过忽略反斜线转义的换行符支持连续记录,并且允许通过 C 风格的反斜杠转义符嵌入非打印字符数据。

当数据为列表、名称(在首字段)为关键字、而且记录通常很短(少于 80 个字符)时,这种格式最适用。这种格式和传统的 Unix 工具配合得很好。

有时候也可以看到冒号以外的字段分隔符,如管道字符“|”,甚至用 ASCII NUL。Unix 的旧学派做法偏爱 TAB,这可在 cut (1) 和 paste(1) 的默认设置中反映出来。但随着格式设计者逐渐意识到,TAB 和 SPACE 在视觉上无法区别而引起了很多令人恼火的小麻烦,这种做法也逐渐改变了。

这种格式之于 Unix,就像 CSV(逗号分隔值)格式之于 Unix 世界外的 Microsoft Windows 和其它操作系统。Unix 中很少用到以逗号分隔字段、双引号用来转义逗号、没有连续行的 CSV 格式。

事实上,Microsoft 版 CSV 是一个如何设计文本文件格式的典型反面例子。问题首先出现在字段正好含有分隔字符(在这种情况下是逗号)的情况中。Unix 的方法是简单的用反斜杠转义分隔符,用双反斜杠表示反斜杠字面值。在解析文件时,这种设计只要检查一种特殊情况(转义符),发现转义符时只要一个操作(解析跟在转义符后的字符)。后者不仅方便了分隔符的处理,而且还能自由处理转义符和新行符。CSV 则相反,如果字段值中存在分隔符,就将整个字段值包括在双引号内。如果字段值包含双引号,整个字段值也得包括在双引号内,字段中的单个双引号需要重复两遍才能表明自己并不结束整个字段。

到处使用特殊情况所带来的不良结果是双重的。首先,分析程序的复杂度(以及 bug 的易发性)提高了。其次,由于格式规定既复杂又不明确,不同实现对边缘情况的处理也不同。有时,通过在一行的最后一个字段前使用双引号来支持连续行——但只有部分产品这么做!在微软自己的应用软件,有时甚至是同一个应用程序的不同版本之间(Excel 就是最明显的例子),CSV 文件都存在不兼容的情况。

可是 CSV 在今天的很多场景下仍然大行其道。可见更好的技术或者规范并不一定会在现实应用中得到更多的关注。在现实中,更多的是实用主义。

1 个月 后

回复 第7楼 的 肖楠:那要怎么解决csv读数据不会有缺失值的问题呢。实话说,没太明白你的point