【问题标题】:postgres generate array using slide windowpostgres 使用滑动窗口生成数组
【发布时间】:2021-01-15 07:47:54
【问题描述】:

我试图弄清楚如何使用 Postgre 在字符列上给定一个滑动窗口来生成一个 ARRAY 查询。

例如,如果我有这个:

   pid           
   <chr>         
 1 WP_096038768.1
 2 WP_013465871.1
 3 WP_058155244.1
 4 WP_011329269.1
 5 WP_058374608.1
 6 WP_089368983.1
 7 WP_096739105.1
 8 WP_089346667.1
 9 WP_096041177.1
10 WP_010553306.1
...

我想要在行之前和之后的大小为 1 的滑动窗口。 结果是这样的:

   pid            g                                           
   <chr>          <chr>                                       
 1 WP_013465871.1 WP_096038768.1,WP_013465871.1,WP_058155244.1
 2 WP_058155244.1 WP_013465871.1,WP_058155244.1,WP_011329269.1
 3 WP_011329269.1 WP_058155244.1,WP_011329269.1,WP_058374608.1
 4 WP_058374608.1 WP_011329269.1,WP_058374608.1,WP_089368983.1
 5 WP_089368983.1 WP_058374608.1,WP_089368983.1,WP_096739105.1
 6 WP_096739105.1 WP_089368983.1,WP_096739105.1,WP_089346667.1
 7 WP_089346667.1 WP_096739105.1,WP_089346667.1,WP_096041177.1
 8 WP_096041177.1 WP_089346667.1,WP_096041177.1,WP_010553306.1
 9 WP_010553306.1 WP_096041177.1,WP_010553306.1,WP_007376542.1
10 WP_007376542.1 WP_010553306.1,WP_007376542.1,WP_039038284.1
...

感谢任何提示。

这个例子是我用 R 做的:

library(tidyverse)
library(dbplyr)
library(RPostgreSQL) 
library(DBI)

st2tm %>% 
  mutate(
    p1 = lag(pid),
    p2 = lead(pid)
  ) %>% 
  group_by(pid) %>% 
  mutate(g = paste(na.omit(c(p1,pid,p2)), sep = ",")) %>% 
  ungroup() %>% 
  select(-c(p1, p2)) %>% 
  filter(str_count(g,",")==2)

但是当通过 DBI 连接应用于 Postgres 表时,它会失败

Error in vapply(x, escape, character(1), con = con) : 
  values must be length 1,
 but FUN(X[[1]]) result is length 3

pasteError: str_count() is not available in this SQL variantfilter

另外,我认为一些更聪明的策略。

【问题讨论】:

    标签: r postgresql sliding-window dbplyr


    【解决方案1】:

    这很可能是由于 dbplyr 没有为将 na.omitstr_count 转换为 postgresql 定义的翻译(很可能定义了 paste 的翻译)。

    您可以通过早先检查缺失值来替换 str_countna.omit

    st2tm %>% 
      mutate(
        p1 = lag(pid),
        p2 = lead(pid)
      ) %>% 
      filter(!is.na(p1),
             !is.na(p2)) %>%
      mutate(g = paste(p1, ",", pid, ",", p2)) %>% 
      select(-c(p1, p2)) %>% 
    

    如果paste 是问题,你可以用postgresql 的内置CONCAT 函数替换它。

    st2tm %>% 
      mutate(
        p1 = lag(pid),
        p2 = lead(pid)
      ) %>% 
      filter(!is.na(p1),
             !is.na(p2)) %>%
      mutate(g = CONCAT(p1, ",", pid, ",", p2)) %>% 
      select(-c(p1, p2)) %>% 
    

    因为CONCAT 不是 R 函数,dbplyr 会将其按写入方式传递给 postgresql,而不是尝试翻译它。

    【讨论】:

    • 谢谢。 CONCAT 生成一个字符串,如果我想要一个ARRAY 而不是/有一个函数可以做到吗?
    • 我不知道有任何 dbplyr 翻译可以很好地与更高级的数据类型(如数组)配合使用。您可能可以使用与CONCAT 相同的想法,并将不可翻译的转换为数组的命令传递给 dbplyr,dbplyr 会将其传递给 postgresql。但是您随后可能会发现很难将此列与标准 dplyr 动词一起使用,并且您将不得不继续使用非翻译技巧。到那时,直接在 postgresql 中工作是值得的。
    猜你喜欢
    • 2020-12-25
    • 2019-12-17
    • 1970-01-01
    • 2020-05-19
    • 2012-12-30
    • 2021-10-29
    • 2022-01-03
    • 1970-01-01
    相关资源
    最近更新 更多