带 dplyr R 的笛卡尔积
cartesian product with dplyr R
我正在寻找笛卡尔积的 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
我已经在寻找这个(例如 here or here)但没有找到任何有用的东西。
非常感谢
expand.grid(x=c("a","b","c"),y=c(1,2,3))
编辑:还要考虑以下来自“Y T”的优雅解决方案,用于更复杂的 data.frame:
简而言之:
expand.grid.df <- function(...) Reduce(function(...) merge(..., by=NULL), list(...))
expand.grid.df(df1, df2, df3)
如果我们需要 tidyverse
输出,我们可以使用 expand
from tidyr
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
当遇到这个问题时,我倾向于这样做:
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() 选项都要简洁可以想出
使用 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
向所有人致歉:下面的示例 not 似乎适用于 data.frames 或 data.tables.
当 x 和 y 是数据库 tbl
s (tbl_dbi
/ tbl_sql
) 时,您现在还可以:
full_join(x, y, by = character())
于 2017 年底添加到 dplyr,并在 DB 世界中被翻译成 CROSS JOIN
。省去了引入假变量的麻烦。
这是 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 秒。
使用上面的两个答案,使用 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
我正在寻找笛卡尔积的 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
我已经在寻找这个(例如 here or here)但没有找到任何有用的东西。
非常感谢
expand.grid(x=c("a","b","c"),y=c(1,2,3))
编辑:还要考虑以下来自“Y T”的优雅解决方案,用于更复杂的 data.frame:
简而言之:
expand.grid.df <- function(...) Reduce(function(...) merge(..., by=NULL), list(...))
expand.grid.df(df1, df2, df3)
如果我们需要 tidyverse
输出,我们可以使用 expand
from tidyr
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
当遇到这个问题时,我倾向于这样做:
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() 选项都要简洁可以想出
使用 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
向所有人致歉:下面的示例 not 似乎适用于 data.frames 或 data.tables.
当 x 和 y 是数据库 tbl
s (tbl_dbi
/ tbl_sql
) 时,您现在还可以:
full_join(x, y, by = character())
于 2017 年底添加到 dplyr,并在 DB 世界中被翻译成 CROSS JOIN
。省去了引入假变量的麻烦。
这是 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 秒。
使用上面的两个答案,使用 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