【问题标题】:Read csv with numeric columns containing thousands separator [duplicate]使用包含千位分隔符的数字列读取 csv [重复]
【发布时间】:2015-10-06 13:05:07
【问题描述】:

我尝试读取的 csv 文件具有以下格式:

Date,x,y
"2015/08/01","71,131","20,390"
"2015/08/02","81,599","23,273"
"2015/08/03","79,435","21,654"
"2015/08/04","80,733","20,924"

分隔符是逗号,但每个值也用引号括起来,因为逗号用作千位分隔符。我尝试了来自 {readr} 的 read.csvread_csv 和来自 {data.table} 的 fread ,我能做的最好的事情就是读取所有值作为字符串,然后使用 as.numericgsub 的组合来将它们转化为数字。

我还发现了这个:Most elegant way to load csv with point as thousands separator in R 它非常有用,但是我的数据有很多列(并非都是数字),我宁愿不指定列类型。

有什么想法或者我应该开始 gsub-ing 吗?有趣的是,Excel 可以很好地读取文件:)

【问题讨论】:

  • 你知道哪些列需要转换吗?
  • @Jaap 我猜,但至少它会正确读取它。啊刚刚看到他们已经尝试过了。非虚拟机
  • 大卫 - 我不确定那会完成什么。无论如何,我收到此错误:` Expected sep (' ') but new line, EOF (or other non printing character) 在检测类型时结束字段 4 (first): Enter the new date: (mm-dd-yy) `
  • 因为您需要以正确的格式阅读它,所以我无法在 cmets 中对其进行格式化。买我猜你已经尝试过了。
  • @Jaap - 现在我知道(大约 40 列)。不过以后会加栏目,不想每次都手动修改。

标签: r csv


【解决方案1】:

您应该可以使用read.csv 读取数据。这里是一个例子

#write data
write('Date,x,y\n"2015/08/01","71,131","20,390"\n"2015/08/02","81,599","23,273"\n"2015/08/03","79,435","21,654"\n"2015/08/04","80,733","20,924"',"test.csv")

#use "text" rather than "file" in read.csv
#perform regex substitution before using read.csv
#the outer gsub with '(?<=\\d),(\\d{3})(?!\\d)' performs the thousands separator substitution
#the inner gsub replaces all \" with '
read.csv(text=gsub('(?<=\\d),(\\d{3})(?!\\d)',
                   '\\1',
                   gsub("\\\"",
                        "'",
                        paste0(readLines("test.csv"),collapse="\n")),
                   perl=TRUE),
         header=TRUE,
         quote="'",
         stringsAsFactors=FALSE)

结果

#        Date     x     y
#1 2015/08/01 71131 20390
#2 2015/08/02 81599 23273
#3 2015/08/03 79435 21654
#4 2015/08/04 80733 20924

【讨论】:

  • @BogdanC 请检查一些示例数据。很难事先说正则表达式是否正确处理了所有可能的输入。
  • @cyro - 哇!我根本没有考虑过正则表达式。我在一些真实数据上进行了测试,效果很好,我喜欢我不必针对列名或类型进行调整。谢谢!
  • @BogdanC 很高兴它成功了!顺便说一句:您可以通过包含封闭引号" 来使正则表达式模式更具限制性(因此可能更安全)。
【解决方案2】:

使用data.table 包,您可以按如下方式进行:

1:创建要转换的列名向量。在这种情况下,Date 必须被排除。

cols <- setdiff(names(dt),"Date")

2:对其余列应用转换函数:

library(data.table)
dt[, (cols) := lapply(.SD, function(x) as.numeric(gsub(",", "", x))), .SDcols = cols]

这会导致:

> dt
         Date     x     y
1: 2015/08/01 71131 20390
2: 2015/08/02 81599 23273
3: 2015/08/03 79435 21654
4: 2015/08/04 80733 20924

使用过的数据:

dt <- fread('Date,x,y
            "2015/08/01","71,131","20,390"
            "2015/08/02","81,599","23,273"
            "2015/08/03","79,435","21,654"
            "2015/08/04","80,733","20,924"')

【讨论】:

    【解决方案3】:

    最好的解决方案是在导出之前从 Excel 工作表中删除所有这些格式。

    如果做不到这一点,只需使用lapply 转换每一列:

    df[c("x", "y")] <- lapply(df[c("x", "y")], function(x) as.numeric(gsub(",", "", x)))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-04
      • 1970-01-01
      • 2012-04-22
      相关资源
      最近更新 更多