R:为什么 expand.grid() 产生的行比我预期的多?

R: Why is expand.grid() producing many more rows than I expect?

我的理解是,base::grid.expand()tidyr::grid_expand()将return一个对象与一行的每个唯一值联合分布在一个或多个向量上的唯一值。例如,这是我所期望的:

# Preliminaries
library(tidyr)
set.seed(123)

# Simulate data
df <- data.frame(x = as.factor(rep(c(1,2), 50)), y= as.factor(sample(1:3, 100, replace = T)))

# Expected result
data.frame(x = rep(1:2, 3), y = rep(1:3, 2)) # 6 rows!

但是,当我实际使用这些函数时,我得到的(重复的)行比我预期的要多:

# Tidyverse result
tidyr::expand_grid(df) # produces 100 rows!
tidyr::expand_grid(df$x, df$y) # produces 10k rows!

# Base R version
base::expand.grid(df) # produces 10k rows!
base::expand.grid(df$x, df$y) # produces 10k rows!

# Solution...but why do I have to do this?!
unique(base::expand.grid(df))

有人可以解释一下我对它应该做什么的遗漏吗?

expand_grid的输入是可变的(...),我们可以使用do.call

do.call(expand_grid, df)

invoke

library(purrr)
invoke(expand_grid, df)
# A tibble: 10,000 × 2
   x     y    
   <fct> <fct>
 1 1     3    
 2 1     3    
 3 1     3    
 4 1     2    
 5 1     3    
 6 1     2    
 7 1     2    
 8 1     2    
 9 1     3    
10 1     1    
# … with 9,990 more rows

!!!

expand_grid(!!! df)
# A tibble: 10,000 × 2
   x     y    
   <fct> <fct>
 1 1     3    
 2 1     3    
 3 1     3    
 4 1     2    
 5 1     3    
 6 1     2    
 7 1     2    
 8 1     2    
 9 1     3    
10 1     1    
# … with 9,990 more rows

正如@Mossa 评论的那样,return 独特组合的函数将是 expandcrossing 因为 expand 在 [=24= 上调用 expand_grid ] 值

> expand(df, df)
# A tibble: 6 × 2
  x     y    
  <fct> <fct>
1 1     1    
2 1     2    
3 1     3    
4 2     1    
5 2     2    
6 2     3    

基于源代码

getAnywhere("expand.data.frame")
function (data, ..., .name_repair = "check_unique") 
{
    out <- grid_dots(..., `_data` = data)
    out <- map(out, sorted_unique)
    out <- expand_grid(!!!out, .name_repair = .name_repair)
    reconstruct_tibble(data, out)
}

expand.grid 不会尝试 return 只有输入向量的唯一值。它将始终输出一个数据帧,该数据帧的行数与其输入向量的长度的乘积相同:

nrow(expand.grid(1:10, 1:10, 1:10))
#> [1] 1000

nrow(expand.grid(1, 1, 1, 1, 1, 1, 1, 1, 1))
#> [1] 1

如果您查看 expand.grid 的源代码,它会采用可变点并将它们转换为名为 args 的列表。然后它包括以下行:

d <- lengths(args)

其中 return 是一个向量,我们输入 expand.grid 的每个向量都有一个条目。在 expand.grid(df$x, df$y) 的情况下,d 等同于 c(100, 100).

然后是下一行

orep <- prod(d)

得到 d 的乘积,即 100x100,即 10,000。

稍后在函数中使用变量orep来重复每个向量,使其长度等于值orep

如果您只想要两个输入向量的唯一组合,则必须在 expand.grid.

的输入处将它们设为 unique