清理代码并防止null值崩溃,以免read.csv.sql

时间:2018-10-18 21:03:58

标签: sql r conditional read.csv

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

这是一个小的数据集,因此可以重现我的问题:

write.csv(iris, "iris.csv", row.names = F)
library(sqldf)
csvFile <- "iris.csv"

使用read.csv.sql后,我发现您必须使用的符号极其尴尬,以下是我在文件中的读取方式:

# Step 1 (Assume these values are coming from UI)
spec <- 'setosa'
petwd <- 0.2

# Add quotes and make comma-separated:
spec <- toString(sprintf("'%s'", spec)) 
petwd <- toString(sprintf("'%s'", petwd)) 

# Step 2 - Conditionally read in the data, store in 'd'
d <- fn$read.csv.sql(csvFile, sql='select * from file where 
                                  "Species" in ($spec)'
                                  and "Petal.Width" in ($petwd)',
                     filter = list('gawk -f prog', prog = '{ gsub(/"/, ""); print }'))

我的 main 问题是,如果上面的任何值(来自UI)为null,则它将无法正确读取数据,因为这部分代码都是硬编码的。 /> 我想将其更改为:步骤1-检查哪些值是空值并且不从中过滤掉,然后使用read.csv.sql过滤对应列上的所有非空值。

注意:我正在此问题中重复使用此similar question中的代码。

更新
我想弄清楚我的要求。这就是我想要做的:

如果某个字段说specNA(表示用户未选择输入),那么我希望它按这样进行过滤(默认为spec == EVERY SPEC):

# Step 2 - Conditionally read in the data, store in 'd'
d <- fn$read.csv.sql(csvFile, sql='select * from file where 
                                  "Petal.Width" in ($petwd)',
                     filter = list('gawk -f prog', prog = '{ gsub(/"/, ""); print }'))

由于specNA,如果您尝试过滤/读取匹配spec == NA的文件,由于我的数据中没有NA值,它将读取一个空数据集,因此破坏了代码和程序。希望这能进一步清除它。

1 个答案:

答案 0 :(得分:0)

有几个问题:

  • 问题链接中提供的某些简化未得到遵守。
  • spec是一个标量,因此只能使用'$spec'
  • petwd是一个数字标量,SQL不需要数字引号,因此只需使用$petwd
  • 该问题表明您要处理空字段,但不是处理空字段,因此我们使用csvfix将其映射为-1并去除引号。 (或者让他们输入并在R中执行操作。空数字将通过0表示,而空字符字段将作为零长度的字符表示。)
  • 您可以在SQL中使用[...]代替“ ...”

下面的代码通过bash shell在Windows和Ubuntu Linux中都对我有用。

library(sqldf)

spec <- 'setosa'
petwd <- 0.2

d <- fn$read.csv.sql(
  "iris.csv", 
  sql = "select * from file where [Species] = '$spec' and [Petal.Width] = $petwd", 
  verbose = TRUE, 
  filter = 'csvfix map -smq -fv "" -tv -1'
)

更新

关于问题末尾的更新,已澄清了NA可能位于spec中,而不是位于要读取的数据中,并且如果spec为NA,则涉及的条件spec应该被视为TRUE。在这种情况下,只需展开SQL where条件即可,如下所述。

spec <- NA
petwd <- 0.2

d <- fn$read.csv.sql(
  "iris.csv", 
  sql = "select * from file 
         where ('$spec' == 'NA' or [Species] = '$spec') and [Petal.Width] = $petwd", 
  verbose = TRUE, 
  filter = 'csvfix echo -smq'
)

上面的代码将返回Petal.Width为0.2的所有行。