【问题标题】:Notation issues with read.csv.sql in rr 中 read.csv.sql 的符号问题
【发布时间】:2019-03-21 05:31:06
【问题描述】:

我正在使用read.csv.sql 有条件地读取数据(我的数据集非常大,所以这是我选择过滤它并缩小它的解决方案 之前 读取数据)。我通过读取完整数据然后过滤它遇到了内存问题,这就是为什么我使用条件读取以便读取子集而不是完整数据集很重要的原因。
这是一个小数据集,因此可以重现我的问题:

write.csv(iris, "iris.csv", row.names = F)

我发现使用read.csv.sql 时您必须使用的符号非常尴尬,以下是我尝试在文件中读取的第一种方法,它可以工作,但很混乱:

library(sqldf)
csvFile <- "iris.csv"

spec <- 'setosa'
sql <- paste0("select * from file where Species = '\"", spec,"\"'")
d1 <- read.csv.sql(file = csvFile, sql = sql)

然后我发现了另一种以稍微干净的方式编写相同符号的方法是:

sql <- paste0("select * from file where Species = '", spec,"'")
d2 <- read.csv.sql(file = csvFile, sql = sql, 
                   filter = list('gawk -f prog', prog = '{ gsub(/"/, ""); print }'))

接下来,我想阅读从同一列中选择多个值的情况,所以我尝试了这个并且它有效:

d3 <- read.csv.sql(file = csvFile, 
                   sql = "select * from file where Species in 
                         ('\"setosa\"', '\"versicolor\"') ")

但是,我想避免像这样对值进行硬编码,所以我尝试了:

spec2 <- c('setosa', 'versicolor')
sql2 <- paste0("select * from file where Species in '", spec2,"'")
d4 <- read.csv.sql(file = csvFile, sql = sql2, 
                   filter = list('gawk -f prog', prog = '{ gsub(/"/, ""); print }'))

但这不起作用(它似乎只从向量中读取第一个值并尝试将其作为表格进行匹配)。我确定这又是另一个符号问题,希望帮助清理这段代码。
另外,如果您对使用read.csv.sql 和处理符号问题有任何提示/技巧,我很想听听!

【问题讨论】:

  • 为什么需要使用read.csv.sql?您可能会查看library(sqldf),它可以让您编写更自然的查询,例如sqldf("Select * from iris where Species = 'versicolor'")
  • 或者你可以考虑使用dplyr,它的功能类似于SQL,但专为R设计,例如library(dplyr); iris %&gt;% filter(Species %in% spec2)
  • 由于内存问题,我需要在读取文件之前过滤文件,我无法读取完整文件然后过滤。否则我会很乐意使用dplyr

标签: r sqldf read.csv


【解决方案1】:

问题是 sqldf 提供了文本预处理工具,但问题中显示的代码没有使用它们,因此过于复杂。

1) 关于文本替换,请使用fn$(来自 sqldf 自动加载的 gsubfn),如 github page for sqldf 中所述。假设我们在 write.csv 中使用了 quote = FALSE,因为 sqlite 本身不处理引号:

spec <- 'setosa'
out <- fn$read.csv.sql("iris.csv", "select * from file where Species = '$spec' ")

spec <- c("setosa", "versicolor")
string <- toString(sprintf("'%s'", spec)) # add quotes and make comma-separated
out <- fn$read.csv.sql("iris.csv", "select * from file where Species in ($string) ")

2) 关于删除双引号,更简单的方法是使用以下filter= 参数:

read.csv.sql("iris.csv", filter = "tr -d \\042") # Windows

read.csv.sql("iris.csv", filter = "tr -d \\\\042") # Linux / bash

取决于你的外壳。第一个在 Windows 上为我工作(安装了 Rtools 并在 PATH 上),第二个在带有 bash 的 Linux 上为我工作。其他 shell 可能需要其他变体。

2a) 删除引号的另一种方法是在您的系统上安装免费的 csvfix 实用程序(在 WindowsLinuxMac 上可用),然后使用以下 filter=应该在所有 shell 中工作的参数,因为它不涉及通常由 R 或大多数 shell 专门解释的任何字符。因此,以下内容应该适用于所有平台。

read.csv.sql("iris.csv", filter = "csvfix echo -smq")

2b) 另一个可以使用的跨平台实用程序是xsveol= 参数仅在 Windows 上需要,因为 xsv 产生 UNIX 样式的行尾,但在其他平台上不会受到影响,因此以下行应该适用于所有平台。

read.csv.sql("iris.csv", eol = "\n", filter = "xsv fmt")

2c) sqldf 还包括一个可以使用的 awk 程序 (csv.awk)。它输出 UNIX 样式的换行符,因此在 Windows 上指定 eol = "\n"。在其他平台上,如果你指定它不会有什么坏处,但如果你愿意,你可以省略它,因为这是那些平台上的默认设置。

csv.awk <- system.file("csv.awk", package = "sqldf")
rm_quotes_cmd <- sprintf('gawk -f "%s"', csv.awk)
read.csv.sql("iris.csv", eol = "\n", filter = rm_quotes_cmd)

3)关于一般提示,请注意read.csv.sqlverbose=TRUE 参数对于查看它发生了什么很有用。

read.csv.sql("iris.csv", verbose = TRUE)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-07
    • 2018-06-24
    • 2021-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    • 2012-04-12
    相关资源
    最近更新 更多