目录
{: .no_toc}
- 目录 {:toc}
开始
酝酿了很久,是时候写一些关于解决R的数据读入写出的问题了。这毕竟是用R进行数据处理的第一步,很多新手,包括当时的我被各种数据读入写出问题折腾的要死。知识和经验总是会遗忘,所以我准备记录下来,供自己参考,同时也为后人把坑填上。当然,我写的不足的地方,或者有更好的方法,还希望看这篇文章的你不吝指出,一起修正,造福更多的R useR。
问题描述
在读含有多位小数的csv或者excel的时候,总是会发现小数点的位数显示不正确,因为R里面默认的是最多显示7位小数。首先,我们先来看看测试数据长什么样:
原始数据
x1 | x2 | x3 |
---|---|---|
1 | 2.123456780 | 中文测试 |
2 | 4.123456789 | 中文测试 |
3 | 6.11234578 | 中文测试 |
4 | 8.101234767 | 中文测试 |
5 | 10.09012376 | 中文测试 |
6 | 12.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的知识面(就是那些我给出的相关链接),所以希望大家多多转发。