将多个值传播到 R 中数据框中的唯一值

Spread multiple values to unique values in data frame in R

假设我有一个包含姓名列表的数据框:

> x <- c("a", "b", "c")
> x <- as.data.frame(x)

#  > x
# 1 a
# 2 b
# 3 c

我想将每个唯一名称(x,下方)传播到每个名称(y,下方)并在原始列之前创建一个新列,以便新数据框如下所示:

#  > z
# x   y
# a   a
# a   b
# a   c
# b   a
# b   b
# b   c
# c   a
# c   b
# c   c 

这是为了在网络已满的 igraph 中创建“从”“到”边列表。

我该怎么做?有没有我缺少的简单的 tidyverse 解决方案?

使用 dplyrtidyr,您可以:

x %>%
 mutate(y = x) %>%
 complete(y, x)

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

您可以使用 tidyr::expand_gridtidyr::crossing

tidyr::expand_grid(a = x$x, b = x$x)
#tidyr::crossing(a = x$x, b = x$x)

#  a     b    
#  <chr> <chr>
#1 a     a    
#2 a     b    
#3 a     c    
#4 b     a    
#5 b     b    
#6 b     c    
#7 c     a    
#8 c     b    
#9 c     c    

这与基本 R 相似 expand.grid 只是顺序不同。

expand.grid(a = x$x, b = x$x)

基础 R 解决方案:

names <- c("a", "b", "c")

x = rep(names, each=length(names))
y = rep(names, length(names))
df = data.frame(x,y)
df
  x y
1 a a
2 a b
3 a c
4 b a
5 b b
6 b c
7 c a
8 c b
9 c c

您还可以使用 expand 函数来 return 两列的所有可能组合:

library(tidyr)

x %>%
  mutate(y = x) %>%
  expand(x, y)

# A tibble: 9 x 2
  x     y    
  <chr> <chr>
1 a     a    
2 a     b    
3 a     c    
4 b     a    
5 b     b    
6 b     c    
7 c     a    
8 c     b    
9 c     c 

您还可以使用crossing函数:

x <- c("a", "b", "c")
x <- as.data.frame(x)
x$y <- c("a", "b", "c")

crossing(x$x, x$y)        # But you can't just use it within a pipeline since the first argument is not data

# A tibble: 9 x 2
  `x$x` `x$y`
  <chr> <chr>
1 a     a    
2 a     b    
3 a     c    
4 b     a    
5 b     b    
6 b     c    
7 c     a    
8 c     b    
9 c     c 

如果你真的想使用igraph,这里可能是一个选择

make_full_graph(
  length(x),
  directed = TRUE,
  loops = TRUE
) %>%
  set_vertex_attr(name = "name", value = x) %>%
  get.data.frame()

这给出了

  from to
1    a  a
2    a  b
3    a  c
4    b  a
5    b  b
6    b  c
7    c  a
8    c  b
9    c  c