在 R - 从 data.frame 中的所有行生成成对 data.frame

wak*_*ake 3 r dataframe dplyr data.table

我有一个 data.frame df,在 4 列上有 800 万个观察值:

name <- c("Pablo", "Christina", "Steve", "Diego", "Ali", "Brit", "Ruth", "Mia", "David", "Dylan")
year <- seq(2000, 2009, 1)
v1 <- sample(1:10, 10, replace=T)
v2 <- sample(1:10, 10, replace=T)
df <- data.frame(year, v1)

> df
        name year v1 v2
1      Pablo 2000  2  9
2  Christina 2001  5  3
3      Steve 2002  8  9
4      Diego 2003  7  6
5        Ali 2004  2  4
6       Brit 2005  1  1
7       Ruth 2006 10  9
8        Mia 2007  6  7
9      David 2008 10  9
10     Dylan 2009  3  2
Run Code Online (Sandbox Code Playgroud)

我想生成一个 data.frame,output其中的行的所有成对组合df如下所示:

 >output
   name year v1 v2    name_2 year_2 v1_2 v2_2
1 Pablo 2000  2  9 Christina   2001    5    3
2 Pablo 2000  2  9     Steve   2002    8    9
3 Pablo 2000  2  9     Diego   2003    7    6
etc.  
Run Code Online (Sandbox Code Playgroud)

什么是最快的方法来做到这一点?

ali*_*ire 6

tidyr::crossing将返回观察的所有组合,但您需要设置名称setNames等。如果您不想要自我匹配,您可以通过调用dplyr::filter任何唯一 ID 列来删除它们。

library(tidyverse)

df_crossed <- df %>% 
    setNames(paste0(names(.), '_2')) %>% 
    crossing(df) %>% 
    filter(name != name_2)

head(df_crossed)
##   name_2 year_2 v1_2 v2_2      name year v1 v2
## 1  Pablo   2000    5    5 Christina 2001  7  3
## 2  Pablo   2000    5    5     Steve 2002  1  9
## 3  Pablo   2000    5    5     Diego 2003  2  8
## 4  Pablo   2000    5    5       Ali 2004  9  5
## 5  Pablo   2000    5    5      Brit 2005  8  5
## 6  Pablo   2000    5    5      Ruth 2006  8  1
Run Code Online (Sandbox Code Playgroud)

另一种修复名称的方法是使用janitor::clean_namesafter crossing,尽管它是一个额外的包。