我花了一些时间来弄明白这一点。所以,我是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
实际上,过滤器只删除双引号。
那么,如何进行?
答案 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
有什么不同?
/
替换为{}
; ,
中用“_
”替换所有“$&
”。 一个例子:
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的系统,但我无法尝试。