R sqldf、csv和包含逗号的字段

R sqldf、csv和包含逗号的字段,r,sqldf,R,Sqldf,我花了一段时间才弄明白。所以,我是 您有一些.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("

我花了一段时间才弄明白。所以,我是

您有一些.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)
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
sqldf
-解决方案也不起作用:

x <- read.csv.sql("temp.csv", filter = "tr -d '\"' ", header=FALSE)
事实上,过滤器只删除双引号


那么,如何继续呢?

Perl和regex将起到拯救作用。仔细研究并玩弄正则表达式,找到正确的正则表达式并不难:

 s/(\"[^\",]+),([^\"]+\")/$1_$2/g
它与
“……”
匹配,这里的点不是双引号和逗号,而是用下划线代替逗号。perl one liner是传递给sqldf的正确过滤器:

x <- read.csv.sql("temp.csv", 
        filter = "perl -e 's/(\"[^\",]+)_([^\"]+\")/$1_$2/g'", 
        header=FALSE)
现在,弦上的动态美容

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

s{(\"[^\",]+),([^\"]+\")}{$_= $&, s/,/_/g, $_}eg
有什么不同

  • 我将分隔符
    /
    替换为
    {}
  • 最后的选项e指示解析器将替换字段解释为perl代码
  • replecement是一个简单的正则表达式替换,它将匹配子字符串
    $&
    中的所有“
    ”替换为“
    .
    例如:

    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", header=FALSE)
    
    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
    
    x
    V1 V2 V3 V4
    11001艾米9:43:0099.2
    21002“小本·多逗号”9:43:0099.2
    31003“Ben_Sr”9:44:00 99.3
    
    对于windows,sqldf现在附带了trcomma2dot.vbs,默认情况下,它与read.csv2.sql一起执行此操作。尽管发现对于非常大的数据来说速度很慢。(>100万行)


    它提到“tr”用于非基于windows的系统,但我无法尝试

    我已经澄清并改进了常见问题解答,并在此处添加了一个带有链接库的perl代码的gawk版本。我最初将您与其他人混淆,您一定是在我确定名称之前看到的。请注意,
    trcomma2dot
    将所有逗号转换为点,不仅仅是引号中的。在read.csv.sql函数中的
    添加过滤器
    参数时,它在文件(文件,“rt”)中给出错误
    错误:无法打开连接。此外:警告消息:在文件(文件,“rt”)中:无法打开文件“C:\Users\user\AppData\Local\Temp\Rtmpcbqrz6\file4819344504”:没有这样的文件或目录。
    我正在RStudio
    x中写入cmd
    
    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