【问题标题】:Combination of vectors' values with the same positional indices in R向量值与 R 中相同位置索引的组合
【发布时间】:2020-02-14 04:35:04
【问题描述】:

假设我们有以下简化的向量(实际上,它们包含更多的值):

n <- c(1,2)
x <- c(4,5,6) 
y <- c(7,8,9)

#to get all possible combinations, we can use expand.grid 
df <- expand.grid(n=n,
                  x=x,
                  y=y
)

> df
   n x y
   1 4 7
   2 4 7
   1 5 7
   2 5 7
   1 6 7
   2 6 7
   1 4 8
   2 4 8
   1 5 8
   2 5 8
   1 6 8
   2 6 8
   1 4 9
   2 4 9
   1 5 9
   2 5 9
   1 6 9
   2 6 9

但是,我希望向量 x, y 具有仅考虑具有相同索引值的元素的组合,即 (x1, y1), (x2 , y2), (x3, y3) 但不是 (x1,y2), (x1,y3) 等。 而向量 n 仍然照常使用(它的所有元素都与 x 和 y 组合的结果“配对”)。

换句话说,我想得到以下df:

   n x y
   1 4 7
   2 4 7
   1 5 8
   2 5 8
   1 6 9
   2 6 9

如果 n 向量有 3 个元素,即 n

   n x y
   1 4 7
   2 4 7
   3 4 7
   1 5 8
   2 5 8
   3 5 8
   1 6 9
   2 6 9
   3 6 9

【问题讨论】:

    标签: r


    【解决方案1】:

    您可以组合需要在一起的对列表,然后在expand.grid中使用它

    expand.grid(n, Map(c, x, y)) %>% tidyr::unnest_wider(Var2)
    

    或者我们也可以使用相同的逻辑使用crossing

    library(tidyverse)
    
    crossing(n, x = map2(x, y, c)) %>%
      unnest_wider(x) %>%
      rename_at(-1, ~c("x", "y"))
    
    #      n     x     y
    #  <dbl> <dbl> <dbl>
    #1     1     4     7
    #2     1     5     8
    #3     1     6     9
    #4     2     4     7
    #5     2     5     8
    #6     2     6     9
    

    【讨论】:

      【解决方案2】:

      我们可以创建一个函数来做到这一点

      f1 <- function(vec1, vec2, n) {
             d1 <- data.frame(x = vec1, y = vec2)
             d2 <- transform(d1[rep(seq_len(nrow(d1)), each = length(n)), ], n = n)
              row.names(d2) <- NULL
              d2[c('n', 'x', 'y')]
        }
      
      
      
      f1(x, y, n = 1:2)
      #  n x y
      #1 1 4 7
      #2 2 4 7
      #3 1 5 8
      #4 2 5 8
      #5 1 6 9
      #6 2 6 9
      
      f1(x, y, n = 1:3)
      #  n x y
      #1 1 4 7
      #2 2 4 7
      #3 3 4 7
      #4 1 5 8
      #5 2 5 8
      #6 3 5 8
      #7 1 6 9
      #8 2 6 9
      #9 3 6 9
      

      或者在tidyverse中

      library(dplyr)
      library(tidyr)
      tibble(x, y) %>% 
           uncount(length(n)) %>% 
           mutate(n = rep(n, length.out = n())) %>%
           select(n, x, y)
      # A tibble: 9 x 3
      #      n     x     y
      #  <int> <dbl> <dbl>
      #1     1     4     7
      #2     2     4     7
      #3     3     4     7
      #4     1     5     8
      #5     2     5     8
      #6     3     5     8
      #7     1     6     9
      #8     2     6     9
      #9     3     6     9
      

      或者先创建一个tibble,然后将其与crossing一起使用

      tibble(x, y) %>%
             crossing(n)
      

      数据

      n <- 1:3
      

      【讨论】:

      • @ama 我遵循与 andrewreece 的解决方案中相同的输出
      • @ama 是的,更新后的代码给出了你展示的模式
      【解决方案3】:

      这是一个 tidyverse 解决方案,使用 purrr::map_df

      library(tidyverse)
      
      map_df(n, ~tibble(n=.x, x, y))
      
            n     x     y
        <dbl> <dbl> <dbl>
      1     1     4     7
      2     1     5     8
      3     1     6     9
      4     2     4     7
      5     2     5     8
      6     2     6     9
      

      如果您需要完全按照示例输出排序的值,请将%&gt;% arrange(x, y) 添加到map 的输出中。

      【讨论】:

        【解决方案4】:

        一种选择是将 x 和 y 粘贴在一起,然后使用扩展网格并使用 tidyr 包中的单独函数分隔列。

        library(dplyr) #for pipe
        library(tidyr) #for separate
        
        n <- c(1,2)
        x <- c(4,5,6) 
        y <- c(7,8,9)
        z <- paste(x, y, sep = "-")
        
        expand.grid(n = n, xy = z) %>% 
          separate(xy, sep = "-", into = c("x", "y")) %>%
          mutate(x = as.numeric(x), y = as.numeric(y)) %>% 
          as.tibble()
        

        【讨论】:

        • 感谢您的解决方案。我不确定最后的 as.tibble() 是否必要。无论如何,这似乎是在 'tibble' 库中找到的。
        • 不,这不是完全必要的,它只是为了匹配输出的确切格式。谢谢
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-08-09
        • 1970-01-01
        • 2011-10-12
        • 2021-11-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多