如何在R中使用read.table读取带有双引号转义值的数据

13

我在使用R语言中遇到了读取包含以下行的文件的问题。

"_:b5507F4C7x59005","Fabiana D\"atri"
任何想法吗?我怎样才能让read.table理解\"是引号的转义符号?
谢谢, Alexandre

1
你可以在示例中添加一两行额外的代码,这样就不会得到仅适用于单行代码的答案了。 - Tommy
请参考如何阅读包含转义引号的引用文本,了解使用readLines在R中的解决方法。 - jnas
7个回答

6

在我看来,read.table/read.csv无法处理转义引号。

...但是我认为我有一个(丑陋的)解决方法,受到@nullglob的启发;

  • 首先不使用引号读取文件。 (这不能处理嵌入的,,如@Ben Bolker所指出的那样)
  • 然后遍历字符串列并删除引号:

测试文件看起来像这样(我添加了一个非字符串列以便查看):

13,"foo","Fab D\"atri","bar"
21,"foo2","Fab D\"atri2","bar2"

以下是代码:

# Generate test file
writeLines(c("13,\"foo\",\"Fab D\\\"atri\",\"bar\"",
             "21,\"foo2\",\"Fab D\\\"atri2\",\"bar2\"" ), "foo.txt")

# Read ignoring quotes
tbl <- read.table("foo.txt", as.is=TRUE, quote='', sep=',', header=FALSE, row.names=NULL)

# Go through and cleanup    
for (i in seq_len(NCOL(tbl))) {
    if (is.character(tbl[[i]])) {
        x <- tbl[[i]]
        x <- substr(x, 2, nchar(x)-1) # Remove surrounding quotes
        tbl[[i]] <- gsub('\\\\"', '"', x) # Unescape quotes
    }
}

输出结果是正确的:
> tbl
  V1   V2          V3   V4
1 13  foo  Fab D"atri  bar
2 21 foo2 Fab D"atri2 bar2

这比我预期的工作量要大。但是@Tommy的解决方案有效!谢谢! - Alexandre Rademaker
如果数据包含分隔符,该怎么办?您不能不带引号读取,否则数据将被拆分。 - Luke
现在,这已经不是最佳答案了... 最好的答案是使用readr :: read_delim(),现在请看下面。 - BurninLeo

4
在Linux/ Unix(或在使用cygwin或GnuWin32的Windows系统上),您可以使用 sed 将转义的双引号\"转换为双倍的双引号"",这样可以很好地处理 read.csv :
p <- pipe(paste0('sed \'s/\\\\"/""/g\' "', FILENAME, '"'))
d <- read.csv(p, ...)
rm(p)

以下的sed命令通常用于预处理CSV输入:

sed 's/\\"/""/g' file.csv

我不认为这很美观,但至少你不必离开R环境...

2

我很抱歉这里的内容不够详细,因为我正在紧张地编写代码。

你可以考虑使用scan()函数。我创建了一个简单的样本文件“sample.csv”,其中包含:

V1,V2
"_:b5507F4C7x59005","Fabiana D\"atri"

以下是两个快速的可能性(包含输出结果,方便您复制粘贴到命令行中):

test <- scan("sample.csv", sep=",", what='character',allowEscapes=TRUE)
## Read 4 items
test
##[1] "V1"                "V2"                "_:b5507F4C7x59005"
##[4] "Fabiana D\\atri\n"

或者

test <- scan("sample.csv", sep=",", what='character',comment.char="\\")
## Read 4 items
test
## [1] "V1"                "V2"                "_:b5507F4C7x59005"
## [4] "Fabiana D\\atri\n"

您可能需要再稍微尝试一下以获得您想要的结果。而且我看到您已经提到了writeLines,所以您可能已经尝试过了。无论如何,祝您好运!


allowEscapesن¹ںوک¯read.csvه’Œread.tableçڑ„ن¸€ن¸ھهڈ‚و•°م€‚ - Joris Meys

1

我通过设置quote参数成功地运行了您的示例:

> read.csv('test.csv',quote="'",head=FALSE)
                   V1                  V2
1 "_:b5507F4C7x59005" "Fabiana D\\"atri" 
2 "_:b5507F4C7x59005" "Fabiana D\\"atri" 

我认为添加 allowEscapes=TRUE 可能会有所帮助,但似乎并没有。 - Ben Bolker
这种方法可以工作,除非文件中有单引号。但是所有字符串最终都被双引号括起来(并且转义的引号仍然被转义),因此需要进行更多处理... - Tommy
正如@Ben所发的,这个解决方案在我的情况下行不通。我在其他字段中有逗号。 - Alexandre Rademaker

1

readr 包中的 read_delim 函数可以处理转义和双倍双引号,使用参数 escape_doubleescape_backslash

例如,如果我们的文件通过双倍引号来转义引号:

"quote""","hello"
1,2

然后我们使用。
read_delim(file, delim=',')  # default escape_backslash=FALSE, escape_double=TRUE

如果我们的文件使用反斜杠转义引号:
"quote\"","hello"
1,2

我们使用。
read_delim(file, delim=',', escape_double=FALSE, escape_backslash=TRUE)

0

从新版本的R开始,readr::read_delim()是正确的方法。

data = read_delim(filename, delim = "\t", quote = "\"",
    escape_backslash=T, escape_double=F,
    # The columns depend on your data
    col_names = c("timeStart", "posEnd", "added", "removed"),
    col_types = "nncc"
)

-2

使用read.csv()应该没问题。请查看?read.csv的帮助文档 - 指定引号的选项是quote = "...."。但在这种情况下,可能会有一个问题:似乎read.csv()更喜欢看到匹配的引号。

我尝试了相同的操作read.table("sample.txt", header = FALSE, as.is = TRUE),其中sample.txt是您的文本文件,并且它似乎可以工作。当read.csv()无法正常工作时,我倾向于退回到read.table()并仔细指定参数。


不,它不起作用,请尝试一些稍微复杂的东西,比如:writeLines(c("\"foo\",\"Fab D\\\"atri\",\"bar2\"","\"foo2\",\"Fab D\\\"atri2\",\"bar2\"" ), "foo.txt")... - Tommy
请记住,从R的角度来看,您的原始输出仅是每行1个字符串,而不是一堆单独引用的字符串。如果您想在文件中引用整个内容,则需要添加引号。 - Iterator
在使用read.table之后,我得到了a$V2输出[1] ",\"Fab" ",\"Fab",这不正确。...如果你在文本编辑器中打开“foo.txt”,你会看到它包含像OP所述的字符串。 - Tommy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接