【问题标题】:How to get different combination in a character using R?如何使用 R 在角色中获得不同的组合?
【发布时间】:2021-06-25 13:17:00
【问题描述】:

这是我的字符“NGNG”,这里N代表c(“A”、“T”、“C”、“G”)中的任何一个,所以在我的输出中我总共需要16个组合,例如AGAG, TGAG、CGAG、GGAG、TGTG、TGCG、TGGG等。

如果一开始只有一个更改,例如“NGG”,我可以使用 tidyr 的 expand_grid 轻松完成

library(tidyverse)
expand_grid(one = c("A", "T", "C", "G"), two = "NG") %>% 
  mutate(three = paste0(one, two)) %>% 
  pull(three)


[1] "ANG" "TNG" "CNG" "GNG"

但是当 N 出现在它的中间或倍数时,我正在努力寻找一种方法来做到这一点。

【问题讨论】:

    标签: r dplyr combinations


    【解决方案1】:

    expand.grid 后跟do.call 怎么样?

    cart_prod <- expand.grid(c("A", "T", "C", "G"),
                             "G",
                             c("A", "T", "C", "G"),
                             "G")
    do.call(paste0, cart_prod)
    [1] "AGAG" "TGAG" "CGAG" "GGAG" "AGTG" "TGTG" "CGTG" "GGTG"
    [9] "AGCG" "TGCG" "CGCG" "GGCG" "AGGG" "TGGG" "CGGG" "GGGG"
    

    说明

    由于 OP 要求索引 2 和 4 保持为“G”,我们只需让第一个 1st 和 3rd 参数在可能的选择上有所不同:@ 987654326@。现在,使用前 4 个参数调用 expand.grid

    c("A", "T", "C", "G")
    "G"
    c("A", "T", "C", "G")
    "G"
    

    将产生一个与我们想要的结果同构的data.frame,因为expand.grid 返回Cartesian product

    expand.grid(c("A", "T", "C", "G"),
                "G",
                c("A", "T", "C", "G"),
                "G")
       Var1 Var2 Var3 Var4
    1     A    G    A    G
    2     T    G    A    G
    3     C    G    A    G
    4     G    G    A    G
    5     A    G    T    G
    6     T    G    T    G
    7     C    G    T    G
    8     G    G    T    G
    9     A    G    C    G
    10    T    G    C    G
    11    C    G    C    G
    12    G    G    C    G
    13    A    G    G    G
    14    T    G    G    G
    15    C    G    G    G
    16    G    G    G    G
    

    现在,剩下的就是将列粉碎在一起。我们利用do.callpaste0 来实现这一点。

    为什么do.call(paste0, some_data.frame) 有效?

    我在do.call 上找到了这个很好的解释:The {do.call} function。这是第一行:

    “R 有一个有趣的函数,叫做 do.call。这个函数允许你调用任何 R 函数,但是你可以使用一个列表来保存函数的参数,而不是一个一个地写出参数。”

    由于data.frame 本质上是一个list,我们可以按照通常的方式使用do.call

    由于cart_prod 的每一列只是一个向量,paste0 按元素组合每一列。例如,第一列和第二列是:

    cart_prod$Var1
    [1] A T C G A T C G A T C G A T C G
    Levels: A T C G
    
    cart_prod$Var2
    [1] G G G G G G G G G G G G G G G G
    Levels: G
    

    paste0 应用于这两个,给出:

    paste0(cart_prod$Var1, cart_prod$Var2)
    [1] "AG" "TG" "CG" "GG" "AG" "TG" "CG" "GG"
    [9] "AG" "TG" "CG" "GG" "AG" "TG" "CG" "GG"
    

    如您所见,我们开始看到我们想要的结果。如果我们将此结果与第三列结合,我们将得到:

    paste0(paste0(cart_prod$Var1, cart_prod$Var2), cart_prod$Var3)
    [1] "AGA" "TGA" "CGA" "GGA" "AGT" "TGT" "CGT" "GGT"
    [9] "AGC" "TGC" "CGC" "GGC" "AGG" "TGG" "CGG" "GGG"
    

    现在,我们将这个结果与最后一列结合起来:

    paste0(paste0(paste0(cart_prod$Var1, cart_prod$Var2), cart_prod$Var3), cart_prod$Var4)
    [1] "AGAG" "TGAG" "CGAG" "GGAG" "AGTG" "TGTG" "CGTG" "GGTG"
    [9] "AGCG" "TGCG" "CGCG" "GGCG" "AGGG" "TGGG" "CGGG" "GGGG"
    

    瞧!我们得到了我们想要的结果。

    【讨论】:

    • 这非常简单,也使我能够将结果包装在一个函数中,以调用任意长度和组合的字符。使用paste0do.call 简化了我在数据框本身内部进行操作时所苦苦挣扎的最终过程。我从来没有使用过do.call,我想从现在开始我会更频繁地使用它。
    【解决方案2】:

    这是一种关于如何实现所需输出的奇怪方法: 以下是有关此解决方案的一些注意事项:

    • 我将 map2 函数包裹在花括号中,因此我可以选择 .x.y 作为 %&gt;% 将 LHS(此处为数据框)放在第一个参数中
    • exec 函数在参数列表上应用一个函数,该函数更像是基础 R 中的 do.call 并使用 !!! 将拼接结果列表的元素,以便每个元素成为单个参数,然后由行绑定
    library(purrr)
    
    N <- c("A", "T", "C", "G")
    
    expand.grid(N, N) %>%
      {map2(.$Var1, .$Var2, ~ paste0(.x, "G", .y, "G"))} %>%
      exec(rbind, !!!.)
    
          [,1]  
     [1,] "AGAG"
     [2,] "TGAG"
     [3,] "CGAG"
     [4,] "GGAG"
     [5,] "AGTG"
     [6,] "TGTG"
     [7,] "CGTG"
     [8,] "GGTG"
     [9,] "AGCG"
    [10,] "TGCG"
    [11,] "CGCG"
    [12,] "GGCG"
    [13,] "AGGG"
    [14,] "TGGG"
    [15,] "CGGG"
    [16,] "GGGG"
    

    【讨论】:

    • 这确实很有趣......这个答案中至少有 3 件事我以前从未见过。使用{exec!!!.。 +1 创意!
    • 谢谢。我真的很喜欢将新想法付诸实践,通常我会在我的答案中使用它,希望有人发现我的代码的某些部分很有趣。
    • 我添加了一些描述,希望对您有所帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 2019-11-26
    • 1970-01-01
    相关资源
    最近更新 更多