【问题标题】:readr : Turn off scientific notation in write_csvreadr : 在 write_csv 中关闭科学记数法
【发布时间】:2015-08-01 04:43:42
【问题描述】:

我正在使用 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

【问题讨论】:

  • 你能准备一个小reproducible example来说明问题吗?您确定要将它们视为数值吗?也许将它们转换为字符/因子值?
  • 我想继续使用数字类型。最好知道如何抑制文件写入的科学记数法。

标签: r csv file-io


【解决方案1】:
 require(dplyr)    
 tbl_df = mutate_if(tbl_df, is.numeric, as.integer)

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

【讨论】:

    【解决方案2】:

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

    有了这个补丁,您将在write_csv 中有一个int_use_scientific=FALSE 参数,这将解决您的问题。希望它最终会被合并。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        使用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,数字周围有“”。但它仍然有效。

        【讨论】:

          【解决方案5】:

          使用字符值可能会更安全:

          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 变量,您不需要任何算术运算。

          【讨论】:

          • 谢谢。但我想知道是否有办法关闭数字类型的行为?
          【解决方案6】:

          我建议你使用

          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 将其转换为科学计数法。 当我右键单击并用记事本打开时,它看起来不错,并且我看到了没有科学计数法的原始数字。

          【讨论】:

          • 谢谢!我正在尝试迁移到 readr 包,并希望了解如何在该库中做到这一点。
          猜你喜欢
          • 2018-10-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-01-15
          • 2020-12-26
          • 1970-01-01
          • 2018-06-21
          相关资源
          最近更新 更多