【问题标题】:cartesian product with dplyr R带有 dplyr R 的笛卡尔积
【发布时间】:2017-08-30 21:39:01
【问题描述】:

我正在尝试查找笛卡尔积的 dplyr 函数。 我有两个没有公共变量的简单 data.frame:

x <- data.frame(x=c("a","b","c"))
y <- data.frame(y=c(1,2,3))

我想重现

的结果
merge(x,y)

  x y
1 a 1
2 b 1
3 c 1
4 a 2
5 b 2
6 c 2
7 a 3
8 b 3
9 c 3

我已经寻找过这个(例如herehere),但没有找到任何有用的东西。

非常感谢

【问题讨论】:

  • expand.grid(x$x,y$y)CJ(x$x, y$y) 来自 data.table

标签: r dplyr cartesian-product


【解决方案1】:
expand.grid(x=c("a","b","c"),y=c(1,2,3))

编辑:对于 n 个更复杂的 data.frame,还请考虑以下来自“Y T”的优雅解决方案:

https://stackoverflow.com/a/21911221/5350791

简而言之:

expand.grid.df <- function(...) Reduce(function(...) merge(..., by=NULL), list(...))
expand.grid.df(df1, df2, df3)

【讨论】:

【解决方案2】:

如果我们需要tidyverse 输出,我们可以使用tidyr 中的expand

library(tidyverse)
y %>% 
   expand(y, x= x$x) %>%
   select(x,y)
# A tibble: 9 × 2
#       x     y
#  <fctr> <dbl>
#1      a     1
#2      b     1
#3      c     1
#4      a     2
#5      b     2
#6      c     2
#7      a     3
#8      b     3
#9      c     3

【讨论】:

    【解决方案3】:

    当遇到这个问题时,我倾向于做这样的事情:

    x <- data.frame(x=c("a","b","c"))
    y <- data.frame(y=c(1,2,3))
    x %>% mutate(temp=1) %>% 
    inner_join(y %>% mutate(temp=1),by="temp") %>%
    dplyr::select(-temp) 
    

    如果 x 和 y 是多列数据框,但我想将 x 行与 y 行组合起来,那么这比我能想到的任何 expand.grid() 选项都更简洁

    【讨论】:

      【解决方案4】:

      使用tidyr 包中的crossing

      x <- data.frame(x=c("a","b","c"))
      y <- data.frame(y=c(1,2,3))
      
      crossing(x, y)
      

      结果:

         x y
       1 a 1
       2 a 2
       3 a 3
       4 b 1
       5 b 2
       6 b 3
       7 c 1
       8 c 2
       9 c 3
      

      【讨论】:

        【解决方案5】:

        向所有人致歉:以下示例是否似乎适用于 data.frames 或 data.tables。

        当 x 和 y 是数据库 tbls (tbl_dbi / tbl_sql) 你现在也可以这样做:

        full_join(x, y, by = character())

        在 2017 年底添加到 dplyr,并且在 DB 世界中也被翻译为 CROSS JOIN。省去了引入假变量的麻烦。

        【讨论】:

        • 我正在使用 dplyr 0.7.6 运行,这给出了给定示例的错误 Error in full_join_impl(x, y, by_x, by_y, aux_x, aux_y, na_matches) : by must specify variables to join by。有什么想法吗?
        • 与 dplyr 0.7.8 的 @Lyngbakr 相同的错误。这曾经出现在 dplyr 中吗?没有这个,我使用crossing(),就像在接受的答案中一样。
        • @andyyy 发生此错误时的基础类型是什么?我看到了奇怪和不同的行为,尤其是在 data.tables 上。
        【解决方案6】:

        这是 dsz 评论的延续。想法来自:http://jarrettmeyer.com/2018/07/10/cross-join-dplyr

        tbl_1$fake <- 1
        tbl_2$fake <- 1
        my_cross_join <- full_join(tbl_1, tbl_2, by = "fake") %>%
                         select(-fake)
        

        我对大小从 4 到 640 obs 的四列数据进行了测试,耗时约 1.08 秒。

        【讨论】:

        • 我喜欢这个。它既好又简单,但根据我的经验,性能不是很好。
        【解决方案7】:

        使用上面的两个答案,使用full_join()by = character() 似乎更快:

        library(tidyverse)
        library(microbenchmark)
        
        df <- data.frame(blah = 1:10)
        
        microbenchmark(diamonds %>% crossing(df))
        Unit: milliseconds
                              expr      min       lq     mean   median       uq     max neval
         diamonds %>% crossing(df) 21.70086 22.63943 23.72622 23.01447 24.25333 30.3367   100
        microbenchmark(diamonds %>% full_join(df, by = character()))
        Unit: milliseconds
                                                 expr      min       lq     mean   median       uq      max neval
         diamonds %>% full_join(df, by = character()) 9.814783 10.23155 10.76592 10.44343 11.18464 15.71868   100
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-05-06
          • 1970-01-01
          • 2021-09-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多