readr:在write_csv中关闭科学记数法

时间:2015-05-20 05:40:21

标签: r csv file-io

我使用R来处理人口普查数据,该数据使用非常长的数字GEOID来识别地理位置。我面临的问题是,当使用write_csv(来自readr包)写出处理过的数据时,它正在用科学记数法编写这些GEOID。有办法解决这个问题吗?

注意:我可以通过将scipen选项设置为足够大的值来切换R控制台上的科学记数法显示。但是这个设置似乎没有扩展到readr库。

这是一个玩具数据集:

library(dplyr)
library(readr) # which is the package with write_csv
(tbl_df(data.frame(GEOID = seq(from=60150001022000, to=60150001022005, 1))))
Source: local data frame [6 x 1]

           GEOID
1 60150001022000
2 60150001022001
3 60150001022002
4 60150001022003
5 60150001022004
6 60150001022005

write_csv((tbl_df(data.frame(GEOID = seq(from=60150001022000, to=60150001022005, 1)))), "test.csv")

这就是我目前所获得的。我正在寻找一种方法来获得与上面相同的数字:

GEOID
6.02E+13
6.02E+13
6.02E+13
6.02E+13
6.02E+13
6.02E+13

6 个答案:

答案 0 :(得分:11)

我宁愿建议重新编码这些列以输入std::out_of_range,因为如果是这样int将不再使用科学数字编码。要在一次传递中转换所有数字列(例如,如果您正在处理计数矩阵),您可以这样做:

write_*

答案 1 :(得分:8)

我写了一个pull request的补丁,以改善write_csv中科学记数法的控制。

使用此补丁,int_use_scientific=FALSE中的write_csv参数可以解决您的问题。希望它最终会合并。

答案 2 :(得分:4)

使用字符值可能更安全:

X <- tbl_df(data.frame(GEOID = as.character(seq(from=60150001022000, to=60150001022005))))

 write_csv(X, "test.csv")

有点讽刺的是,write_csv函数确实将其部分输出强制转换为字符值,而不是数字列。只有当列通过is.object测试时才会被强制执行。似乎没有一个开关可以保持最大精度。 write.table及其后代write.csv函数有几个开关,可以抑制引号和其他允许定制输出的设置,但write_csv几乎没有。

你可以欺骗write_csv认为数字列更复杂,这确实会产生as.character输出,尽管有引号。

 class(X[[1]])<- c("num", "numeric")
 vapply(X, is.object, logical(1))
#GEOID 
# TRUE 

 write_csv(X, "")
#[1] #"\"GEOID\"\n\"60150001022000\"\n\"60150001022001\"\n\"60150001022002\"\n\"60150001022003\"\n\"60150001022004\"\n\"60150001022005\"\n"

作为最佳做法,我不同意您坚持认为ID变量仍为数字的选择。可以将太多暴力应用于对象的存储模式。您不需要任何ID变量的算术运算。

答案 3 :(得分:2)

使用bit64,它是64位整数矢量的S3类

library(dplyr)
library(readr)
options(digits = 22)
tbl_df <- data.frame(GEOID = seq(from=60150001022000, to=60150001022005, 1))
> tbl_df
           GEOID
1 60150001022000
2 60150001022001
3 60150001022002
4 60150001022003
5 60150001022004
6 60150001022005

library(bit64)
tbl_df$GEOID <- as.integer64(tbl_df$GEOID)
write_csv(tbl_df,'test.csv')

如果您在R中再次读取此数据,它将分配正确的数据类型。

dfr <- read_csv('test.csv')
> dfr
Source: local data frame [6 x 1]

           GEOID
1 60150001022000
2 60150001022001
3 60150001022002
4 60150001022003
5 60150001022004
6 60150001022005 

> str(tbl_df)
'data.frame':   6 obs. of  1 variable:  
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   6 obs. of  1 variable:
 $ GEOID: num  6.02e+13 6.02e+13 6.02e+13 6.02e+13 6.02e+13 ...

希望这会有所帮助。我在一个文本编辑器中打开了csv,数字已经&#34;&#34;在他们旁边。但它仍然奏效。

答案 4 :(得分:1)

我建议你使用

write.csv((tbl_df(data.frame(GEOID = seq(from=60150001022000, to=60150001022005, 1)))), "test.csv")

而不是

write_csv((tbl_df(data.frame(GEOID = seq(from=60150001022000, to=60150001022005, 1)))), "test.csv")

如果我打开test.csv,它会在Excel中打开该文件。 Excel将其转换为科学记数法。 当我右键单击并用记事本打开它看起来很好,我看到原始数字没有科学记数法。

答案 5 :(得分:0)

 require(dplyr)    
 tbl_df = mutate_if(tbl_df, is.numeric, as.integer)

我认为在这种情况下导出CSV时将这些列重新编码为字符串会更安全