【问题标题】:How to do a dplyr inner_join col1 > col2如何做一个 dplyr inner_join col1 > col2
【发布时间】:2017-11-24 18:11:37
【问题描述】:

当我不使用标准的“col1”=“col2”连接时,我很难让 dplyr 连接正常工作。以下是我正在经历的两个例子。

首先:

library(dplyr)

tableA <- data.frame(col1= c("a","b","c","d"),
                     col2 = c(1,2,3,4))

inner_join(tableA, tableA, by = c("col1"!="col1")) %>% 
  select(col1, col2.x) %>% 
  arrange(col1, col2.x)

错误:by 必须是(命名的)字符向量、列表或 NULL 自然连接(不推荐在生产代码中使用),不合逻辑

当我复制此代码但使用 sql 时,我得到以下信息:

con <- DBI::dbConnect(RSQLite::SQLite(), ":memory:")

copy_to(con, tableA)

tbl(con, sql("select a.col1, b.col2
              from 
              tableA as a
              inner join 
              tableA as b
              on a.col1 <> b.col1")) %>% 
  arrange(col1, col2)

sql查询结果:

# Source:     SQL [?? x 2]
# Database:   sqlite 3.19.3 [:memory:]
# Ordered by: col1, col2
     col1  col2
     <chr> <dbl>
 1     a     2
 2     a     3
 3     a     4
 4     b     1
 5     b     3
 6     b     4
 7     c     1
 8     c     2
 9     c     4
10     d     1
# ... with more rows

第二部分和上一个类似:

inner_join(tableA, tableA, by = c("col1" > "col1")) %>% 
   select(col1, col2.x) %>% 
   arrange(col1, col2.x)

错误:by 必须是(命名的)字符向量、列表或 NULL 自然连接(不推荐在生产代码中使用),不合逻辑

Sql 等价物:

tbl(con, sql("select a.col1, b.col2
              from tableA as a
              inner join tableA as b
              on a.col1 > b.col1")) %>% 
   arrange(col1, col2)

第二个 sql 查询的结果:

# Source:     SQL [?? x 2]
# Database:   sqlite 3.19.3 [:memory:]
# Ordered by: col1, col2
   col1  col2
  <chr> <dbl>
1     b     1
2     c     1
3     c     2
4     d     1
5     d     2
6     d     3

有谁知道如何创建这些 sql 示例但使用 dplyr 代码?

【问题讨论】:

    标签: r dplyr dbplyr


    【解决方案1】:

    对于您的第一个案例:

    library(dplyr)
    library(tidyr)
    
    expand(tableA, col1, col2) %>% 
      left_join(tableA, by = 'col1') %>% 
      filter(col2.x != col2.y) %>% 
      select(col1, col2 = col2.x)
    

    结果:

    # A tibble: 12 x 2
         col1  col2
       <fctr> <dbl>
     1      a     2
     2      a     3
     3      a     4
     4      b     1
     5      b     3
     6      b     4
     7      c     1
     8      c     2
     9      c     4
    10      d     1
    11      d     2
    12      d     3
    

    对于你的第二种情况:

    expand(tableA, col1, col2) %>% 
      left_join(tableA, by = 'col1') %>% 
      filter(col2.x < col2.y) %>% 
      select(col1, col2 = col2.x)
    

    结果:

    # A tibble: 6 x 2
        col1  col2
      <fctr> <dbl>
    1      b     1
    2      c     1
    3      c     2
    4      d     1
    5      d     2
    6      d     3
    

    【讨论】:

    • 这将非常适用于 R 中的数据框。如果数据框位于数据库上并且您正在使用 dplyr 连接到数据库,这将表明什么。我将编辑主要问题以突出显示这一点。
    • @DyfanJones 问其他问题时,最好问新问题
    【解决方案2】:

    使用dplyrtidyr 的解决方案。这个想法是扩展数据框,然后对原始数据框执行连接。之后,使用fill from tidyrNA 填写到以前的记录中。最后,过滤掉与NA相同值的记录。

    library(dplyr)
    library(tidyr)
    
    tableB <- tableA %>%
      complete(col1, col2) %>%
      left_join(tableA %>% mutate(col3 = col2), by = c("col1", "col2")) %>%
      group_by(col1) %>%
      fill(col3, .direction = "up") %>%
      filter(col2 != col3, !is.na(col3)) %>%
      select(-col3) %>%
      ungroup()
    tableB
    # # A tibble: 6 x 2
    #    col1  col2
    #   <chr> <dbl>
    # 1     b     1
    # 2     c     1
    # 3     c     2
    # 4     d     1
    # 5     d     2
    # 6     d     3
    

    数据

    tableA <- data.frame(col1= c("a","b","c","d"),
                         col2 = c(1,2,3,4), stringsAsFactors = FALSE)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-12
      • 1970-01-01
      • 2019-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多