复杂的循环创建

Complicated loop creation

提问人:GentL 提问时间:10/7/2022 最后编辑:GentL 更新时间:10/12/2022 访问量:53

问:

我需要绝望的帮助,我在 excel 中手动处理了一些数据,这太长了,我想在 R 中使其更加自动化;我有 R 的经验,但还不足以弄清楚如何写出来。所以这里是考虑的数据帧(点击链接不允许我嵌入):

enter image description here

从本质上讲,这是它的开始,源信息是 dataframe1。我本质上是想用相关的数据结果填充 dataframe2 中的相应单元格。所以想象一下,这些只是在每个样本中发现的序列。序列中有一个专门定位的自身修改版本 [MOD],以及一个未修改的版本(第 2 列中没有 [MOD])。我基本上非常非常简单地计算出每个样本的修改百分比。因此,对于样本 1,第一个序列“ABCDEF”,[MOD1] 的 % 是 ((1)/(1+0.5+3))*100 = 22.22% 等,一旦计算出来,它应该进入 dataframe2 的 MOD1(%) 行Sample_1,然后这对每个样本都是如此。然后我进入下一个序列,再次除以修改序列的总值(特定于序列中的位置和修改本身,即 Mod 1 专门基于 G 并重复此操作。

我需要的是一个嵌套循环(我假设一个嵌套循环,我真的不确定):

  1. 搜索第 1 列,收集/突出显示/隔离开始匹配的行,然后在达到差异时停止(即第 1 列第 4 行上的新序列)
  2. 然后它将在第 2 列中搜索修改后的序列,我想我会有一个列表告诉它存在的修改是“MOD1”和“MOD2”等。因此,它将转到第 1-3 行(现在它们已被隔离)第 2 列并找到第一个修改 [MOD1]。
  3. 然后它需要为第一个序列的第一个分离的 MOD1 收集第一个样本(第 3 列)的值,并执行我上面提到的计算,然后创建 dataframe2,它将具有感兴趣的序列,感兴趣的 mod(它所在的)以及第一个 mod 的第一个样本的百分比结果将被放置在其中(dataframe2, 第 3 列,第 1 行)
  4. 然后它需要搜索第二个修改(如果存在)并重复此操作,以在 dataframe2 中再次填充第一个样本的 MOD2(%)
  5. 然后,它需要对 dataframe1 中的每个样本重复此操作,以将此结果信息放入 dataframe2 中
  6. 之后,它将继续搜索“新序列”的下一组行,再次隔离并重复。 对于这种情况的复杂性,我深表歉意(在我看来很复杂,无论谁在阅读都可能不是),我只是想节省时间,因为我必须用数百个序列来做这件事,所以把它放到一个脚本中会非常有帮助。我曾尝试过这方面的尝试,但我在概念化需要按功能完成的工作的第一步中一直失败。

如果您需要任何进一步的背景或信息,请告诉我。

编辑::好吧,这是一个例子,它实际上比我最初想要的要复杂一些(或者至少在我眼中)

df1 <- data.frame(sequence = c(rep("ABC", 3), rep("GHI", 2)),
                  mod = c("ABC[MOD1]", "ABC", "A[MOD1]B[MOD2]C", "G[MOD1]H[MOD1]I", "GHI"),
                  sample_1 = c(1, 0.5, 3, 3, 0.25),
                  sample_2 = c(1.5, 0.75, 2, 1.75, 0.5)) #This is the initial dataframe

df2 <- data.frame(sequence = c(rep("ABC", 3), rep("GHI", 2)),
                  mod = c("[3]MOD1","[1]MOD1","[2]MOD2", "[1]MOD1", "[2]MOD1"),
                  sample_1 = c(0.22,0.67,0.67,0.92,0.92),
                  sample_2 = c(0.35,0.47,0.47,0.78,0.78))

从本质上讲,期望的结果将是修改(MOD1 和 MOD2)分别为它们进行计算,即使它们会产生相同的值,我意识到我仍然需要记下这些信息。此外,由于序列中会有多个修改,并且可能具有相同的修改,因此将它的位置(即 ABC[MOD1] 是位置 [3])与 Mod 类型一起使用将非常有用。

R 循环 嵌套 序列

评论

0赞 Phil 10/7/2022
请在 R 代码中提供示例数据集,而不是图片。data.frame()
0赞 Phil 10/7/2022
取得预期的结果也会有所帮助。

答:

0赞 Phil 10/7/2022 #1

这似乎得到了你想要的:

library(dplyr)
library(stringr)
library(tidyr)
library(purrr)

locate_mod_pos <- function(x) {
  str_locate_all(x, "\\[MOD.\\]") |> 
    map(~ .x |> 
          as_tibble() |> 
          mutate(loc = start - lag(end),
                 loc = if_else(is.na(loc), start - 1L, loc)) |> 
          pull(loc))
}

df1 |> 
  group_by(sequence) |> 
  mutate(across(c(sample_1, sample_2), ~ .x / sum(.x))) |> 
  ungroup() |> 
  mutate(mod_pos = locate_mod_pos(mod),
         mod = str_extract_all(mod, "\\[MOD.\\]")) |> 
  unnest(c(mod, mod_pos)) |> 
  mutate(mod = str_remove_all(mod, "\\[|\\]"),
         mod = paste0("[", mod_pos, "]", mod)) |> 
  select(-mod_pos)

# A tibble: 5 × 4
  sequence mod     sample_1 sample_2
  <chr>    <chr>      <dbl>    <dbl>
1 ABC      [3]MOD1    0.222    0.353
2 ABC      [1]MOD1    0.667    0.471
3 ABC      [2]MOD2    0.667    0.471
4 GHI      [1]MOD1    0.923    0.778
5 GHI      [2]MOD1    0.923    0.778

但是,这适用于您提供的测试数据,但如果特定数据行中出现超过 2 个 [MOD] 实例,我不能 100% 确定它是否有效,因此如果存在这种情况,请检查这是否适用于您的实际数据。

评论

0赞 GentL 10/8/2022
你好!非常感谢!这非常适合我所描述的内容,但是,我意识到原始数据帧和输出需要一些额外的功能,我已将该上下文和示例/输出数据帧放入编辑中。我很抱歉没有在原始帖子中指出这些,我知道这会造成更多的复杂性。我相信,我看到你做了什么,以及你是如何做到的。
0赞 Phil 10/9/2022
如果您能提供结果的确切样子,那将会很有帮助,因为显然我对方括号中数字的含义有些不理解。
0赞 GentL 10/10/2022
你好!是的,我在编辑中输入的 dataframe2 肯定是确切的期望结果。[] 括号中数字的相关性是修改在序列中的位置。在我所看到的中,一个序列可以在序列的不同位置进行多次修改(MOD1 或 MOD2),并且可以在序列中多次进行相同的修改。即使发生这种情况,这些值在技术上是相同的,但它们被放置在一个不同的字母之后,我相信这对我正在做的事情很重要。
0赞 Phil 10/11/2022
在这种情况下,我完全不清楚为什么这些值应该统一为 0,我不明白如果计算值实际上是 0,为什么您添加注释“当然,零将替换为计算值”。
0赞 GentL 10/11/2022
抱歉,我明白你的意思了,我忘了编辑它,它现在已经排序了,它们是现在按照我上面描述的计算值