4

我花了一段时间才弄清楚这一点。所以,我正在回答我自己的问题

你有一些 .csv,你想快速加载它,你想使用这个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)
  

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

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

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

那么,如何进行呢?

4

2 回答 2

3

Perl 和正则表达式来救援。挖掘 SO,并在这里玩弄正则表达式,想出正确的并不难:

 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 在弦上......

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

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

有什么不同?

  1. /{};替换了分隔符
  2. 最后的选项 e 指示解析器将替换字段解释为 perl 代码;
  3. replement 是一个简单的正则表达式替换,它将匹配的 substring 中的所有 " ," 替换为 " " 。_$&

一个例子:

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
于 2011-11-10T21:31:00.203 回答
0

对于 Windows,sqldf 现在带有trcomma2dot.vbs,默认情况下使用 read.csv2.sql 执行此操作。虽然发现它对于非常大的数据很慢。(> 100万行)

它提到了非基于 Windows 的系统的“tr”,但我无法尝试。

于 2015-06-19T19:55:23.077 回答