我使用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
答案 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时将这些列重新编码为字符串会更安全