R数据读入问题——小数点

R数据读入写出系列教程之一

Posted by Elle Liu & Bruce Zhao on April 30, 2016

Estimated reading time: 10 minutes. {R} [readr]

目录

{: .no_toc}

开始

酝酿了很久,是时候写一些关于解决R的数据读入写出的问题了。这毕竟是用R进行数据处理的第一步,很多新手,包括当时的我被各种数据读入写出问题折腾的要死。知识和经验总是会遗忘,所以我准备记录下来,供自己参考,同时也为后人把坑填上。当然,我写的不足的地方,或者有更好的方法,还希望看这篇文章的你不吝指出,一起修正,造福更多的R useR。

问题描述

在读含有多位小数的csv或者excel的时候,总是会发现小数点的位数显示不正确,因为R里面默认的是最多显示7位小数。首先,我们先来看看测试数据长什么样:

原始数据

x1x2x3
12.123456780中文测试
24.123456789中文测试
36.11234578中文测试
48.101234767中文测试
510.09012376中文测试
612.07901275中文测试

一般来说,在R中我们会使用read.csv()这个函数进行文件的读取,简单有效。但是当我们的数据文件对数据精度有一定要求时,read.csv()就显得有些过时了。例如下面:


#setwd("E:\\pretty\\BZRLC投稿")

> getOption("digits")
[1] 7
> test1 <- read.csv("test.csv",header = T,stringsAsFactors = F)
> test1
  x1        x2       x3
1  1  2.123457 中文测试
2  2  4.123457 中文测试
3  3  6.112346 中文测试
4  4  8.101235 中文测试
5  5 10.090124 中文测试
6  6 12.079013 中文测试

注: 如果用read.csv的话,最好要带上stringsAsFactors = F.

可以见到原始数据最多的9位小数的数据,全部自动四舍五入只有6位,如果我们想要全部数据都保留六位小数应该怎么办?那么如何让读入的数据显示正确的小数点位数呢?下面有三种方法可以实现:

解决办法一

options(digits=n)来进行全局设置。


> options(digits=8)
> test1
  x1         x2       x3
1  1  2.1234568 中文测试
2  2  4.1234568 中文测试
3  3  6.1123458 中文测试
4  4  8.1012348 中文测试
5  5 10.0901238 中文测试
6  6 12.0790128 中文测试

> options(digits=10)
> test1
  x1           x2       x3
1  1  2.123456780 中文测试
2  2  4.123456789 中文测试
3  3  6.112345780 中文测试
4  4  8.101234767 中文测试
5  5 10.090123760 中文测试
6  6 12.079012750 中文测试

解决办法二

在原始文件第一行加上你需要的小数点位数,然后删掉第一列就行了。这里最大的小数点位数是9位。


> read.csv("test1.csv",header = T,stringsAsFactors = F)
  x1          x2       x3
1 NA  0.00000001         
2  1  2.12345678 中文测试
3  2  4.12345679 中文测试
4  3  6.11234578 中文测试
5  4  8.10123477 中文测试
6  5 10.09012376 中文测试
7  6 12.07901275 中文测试
> read.csv("test1.csv",header = T,stringsAsFactors = F)
  x1            x2       x3
1 NA  0.0000000001         
2  1  2.1234567800 中文测试
3  2  4.1234567890 中文测试
4  3  6.1123457800 中文测试
5  4  8.1012347670 中文测试
6  5 10.0901237600 中文测试
7  6 12.0790127500 中文测试

不知道你有没有发现read.csv的一个bug,第一行第三列应该为NA,但是这里读成了"",这会对后面的去除NA值的操作造成小坑。请看下面代码与结果:


> b <- read.csv("test1.csv",header = T,stringsAsFactors = F)
> b$x1
[1] NA  1  2  3  4  5  6
> is.na(b$x1)
[1]  TRUE FALSE FALSE FALSE FALSE FALSE FALSE
> is.na(b$x3)
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
> b$x3[1]
[1] ""
> b$x3[1]==""
[1] TRUE

我强烈建议用readr这个包来进行数据的读入。下面给出一个示范,readr功能是很强大,更多例子请见官方教程


> library(readr)
> guess_encoding("test1.csv")
  encoding confidence
1  GB18030          1
> test2<-read_csv("test1.csv",locale=locale(encoding = "GB18030"))
> test2
  x1           x2       x3
1 NA  0.000000001     <NA>
2  1  2.123456780 中文测试
3  2  4.123456789 中文测试
4  3  6.112345780 中文测试
5  4  8.101234767 中文测试
6  5 10.090123760 中文测试
7  6 12.079012750 中文测试
> is.na(test2$x3)
[1]  TRUE FALSE FALSE FALSE FALSE FALSE FALSE

这个方法有一个小坑,我也是刚测试出来的。当系统的默认的小数点位为7时,新增的那一行最多最能到9位,也就是说只能超过系统设置的小数点位数的两位。

解决办法三

目前我认为最有效的一个方法。加载formattable包,此包的作者是任坤,做金融数据分析的,知乎上面有一个得分很高的回答:该如何学习R语言 ,建议大家可以去看看.


library(formattable)

> test1$a <- digits(test1$x2,9)
> test1
  x1        x2       x3            a
1  1  2.123457 中文测试  2.123456780
2  2  4.123457 中文测试  4.123456789
3  3  6.112346 中文测试  6.112345780
4  4  8.101235 中文测试  8.101234767
5  5 10.090124 中文测试 10.090123760
6  6 12.079013 中文测试 12.079012750

这个包是关于处理数据格式的,里面还有关于时间格式的处理,下次会专门讲时间数据的处理方法。

总结

这次就先讲这么一个小点,作为这个系列的开篇。相信大家在读这篇文章的时候不仅找到解决问题的办法,而且还扩充了R的知识面(就是那些我给出的相关链接),所以希望大家多多转发。