sqldf,csv和包含逗号的字段

时间:2011-11-10 21:29:21

标签: r sqldf

我花了一些时间来弄明白这一点。所以,我是answering my own question

你有一些.csv,你想加载它fast,你想使用sqldf包。你常用的代码会被一些恼人的字段所激怒。例如:

1001,     Amy,9:43:00, 99.2
1002,"Ben,Jr",9:43:00, 99.2
1003,"Ben,Sr",9:44:00, 99.3

此代码仅适用于* nix系统。

library(sqldf)
system("touch temp.csv")
system("echo '1001, Amy,9:43:00, 99.2\n1002,\"Ben,Jr\",9:43:00, 99.2\n1003,\"Ben,Sr\",9:44:00, 99.3' > temp.csv")

如果尝试阅读

x <- read.csv.sql("temp.csv", header=FALSE)

R抱怨

Error in try({ : 
  RS-DBI driver: (RS_sqlite_import: ./temp.csv line 2 expected 4 columns of data but found 5)

sqldf - FAQ.13解决方案也不起作用:

x <- read.csv.sql("temp.csv", filter = "tr -d '\"' ", header=FALSE)

再一次,R抱怨

Error in scan(file, what, nmax, sep, dec, quote, skip, nlines, na.strings,  : 
  line 1 did not have 5 elements

实际上,过滤器只删除双引号。

那么,如何进行?

2 个答案:

答案 0 :(得分:3)

Perl和regexes救援。挖掘SO,并用正则表达式here进行操作,找出正确的方法并不太难:

 s/(\"[^\",]+),([^\"]+\")/$1_$2/g

匹配"...,...",这里的点不是双引号和逗号,而是用逗号替换逗号。 perl one-liner是传递给sqldf的正确过滤器:

x <- read.csv.sql("temp.csv", 
        filter = "perl -e 's/(\"[^\",]+)_([^\"]+\")/$1_$2/g'", 
        header=FALSE)

以下是数据框x

> x
    V1       V2      V3   V4
1 1001      Amy 9:43:00 99.2
2 1002 "Ben_Jr" 9:43:00 99.2
3 1003 "Ben_Sr" 9:44:00 99.3

现在,DYO cosmesis on strings ...

编辑:上面的正则表达式只替换字段中第一次出现的逗号。要替换所有的发生,请使用此

s{(\"[^\",]+),([^\"]+\")}{$_= $&, s/,/_/g, $_}eg

有什么不同?

  1. 我将分隔符/替换为{};
  2. 最后的选项e指示解析器将替换字段解释为perl代码;
  3. 补充是一个简单的正则表达式替换,可以在匹配的子字符串,中用“_”替换所有“$&”。
  4. 一个例子:

    system("touch temp.csv")
    system("echo '1001, Amy,9:43:00, 99.2\n1002,\"Ben,Jr,More,Commas\",9:43:00, 99.2\n1003,\"Ben,Sr\",9:44:00, 99.3' > temp.csv")
    

    文件temp.csv如下所示:

    1001,                 Amy,9:43:00, 99.2
    1002,"Ben,Jr,More,Commas",9:43:00, 99.2
    1003,            "Ben,Sr",9:44:00, 99.3
    

    可以用

    阅读
    x <- read.csv.sql("temp.csv", 
           filter = "perl -p -e 's{(\"[^\",]+),([^\"]+\")}{$_= $&, s/,/_/g, $_}eg'", 
           header=FALSE)
    > x
        V1                   V2      V3   V4
    1 1001                  Amy 9:43:00 99.2
    2 1002 "Ben_Jr_More_Commas" 9:43:00 99.2
    3 1003             "Ben_Sr" 9:44:00 99.3
    

答案 1 :(得分:0)

对于windows,sqldf现在带有 trcomma2dot.vbs ,默认使用read.csv2.sql执行此操作。虽然发现它对于非常大的数据来说是慢的(>&gt; 100万行)

提及&#34; tr&#34;对于非基于Windows的系统,但我无法尝试。