【问题标题】:Dplyr filter with str_detect returns empty tibble带有 str_detect 的 Dplyr 过滤器返回空 tibble
【发布时间】:2019-03-09 18:29:42
【问题描述】:

我在 R 中有一个 dplyr 查询,它使用 str_detect 过滤以仅获取以字母“KS”开头的案例,但它返回一个空的小标题。我使用 ROracle 连接到 Oracle 数据库。

table <- tbl(con, "TABLE")

table %>% 
  filter(str_detect(COLUMN, "^KS"))

如果我使用 collect() 来生成 tibble,它可以工作:

table <- collect(tbl(con, "TABLE"))

table %>% 
  filter(str_detect(COLUMN, "^KS"))

这是为什么呢?如果没有收集,我怎样才能让它工作?我需要的一些表格太大而无法收集。

更新: 如果我将其更改为过滤特定列值,如下所示: table %>% filter(str_detect(COLUMN, "^KS")), 有用。由于某种原因,如果没有 collect(),正则表达式将无法工作。

【问题讨论】:

标签: r dplyr stringr roracle


【解决方案1】:

str_detect 转换为对数据库的查询可能存在问题:

b <- tbl(con,"pays")
filter(b,str_detect(nom,"^D")) %>% explain
#<SQL>
#SELECT *
#FROM "pays"
#WHERE (STRPOS("nom", '^D') > 0)


#<PLAN>
#Seq Scan on pays  (cost=0.00..5.31 rows=74 width=13)
#  Filter: (strpos(nom, '^D'::text) > 0)

b %>% filter(str_detect(nom, "^D")) %>% count
## Source:   lazy query [?? x 1]
## Database: postgres 9.6.1 [h2izgk@localhost:5432/postgres]
#      n
#  <dbl>
#1     0

不幸的是,STRPOS(我使用的是 PostgreSQL)无法识别 '^' 的含义并且查询失败。所以你应该使用另一个函数,我发现`grepl 很好:

filter(b,grepl("^D",nom)) %>% explain
#<SQL>
#SELECT *
#FROM "pays"
#WHERE (("nom") ~ ('^D'))


#<PLAN>
#Seq Scan on pays  (cost=0.00..4.76 rows=54 width=13)
#  Filter: (nom ~ '^D'::text)

b %>% filter(grepl("^D", nom))
## Source:   lazy query [?? x 3]
## Database: postgres 9.6.1 [h2izgk@localhost:5432/postgres]
#  nom      pays  code 
#  <chr>    <chr> <chr>
#1 DANEMARK 101   208  
#2 DOUALA   ""    120  
#3 DAKAR    ""    686  
#4 DJIBOUTI 399   262

结果是正确的。 在您的示例中,collect 解决了问题,因为它首先将整个表下载到 R 内存中,然后应用 str_detect 而不转换为 SQL。但效率不高。


【讨论】:

  • 你可能是对的,但在我的情况下,它也不适用于 grepl。 Explain 给我:WHERE (GREPL('^KS', "AVTALE_NR"))
  • 这是因为 Oracle 不是 PostgreSQL。您可以尝试 Oracle 运算符和函数,例如:table %&gt;% filter(locate(COLUMN,"KS")==1)
  • 那个问题也一样,但我很确定你找到了解释。 oracle 无法理解的翻译出现问题。现在我对%like% "%KS%" 的解决方案很满意。
【解决方案2】:

Richard Telford 通过 cmets 中的链接为我指明了正确的方向。如果我改用它,它会起作用:

table <- tbl(con, "TABLE")

table %>% 
  filter(COLUMN %like% "%KS%")

【讨论】:

  • 有趣的是,当filter(collect(b),nom %LIKE% "^D") 因找不到函数%LIKE% 错误而退出时,filter(b,nom %LIKE% "^D") 的包加载最少。这清楚地表明了有效评估事物的位置。
  • 对不起,忘记删除收集了。使用 %like% "%KS%" 我可以在没有 collect() 的情况下工作。
  • 您需要“%KS”还是“%KS%”?在后一种情况下,我对 locate 的建议是不够​​的。
猜你喜欢
  • 1970-01-01
  • 2014-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-09
  • 1970-01-01
  • 2019-04-08
  • 1970-01-01
相关资源
最近更新 更多