【问题标题】:Recoding values by row based on values of other columns根据其他列的值按行重新编码值
【发布时间】:2022-09-23 00:51:39
【问题描述】:

我有一个数据集,其中包含两个父母和 300 多个后代的遗传信息。我正在尝试根据该行中父母的值来更改后代的行值,这样

   P1 P2 o1 o2 o3
1  A  T  A  T  AT
2  C  A  CA A  C
3  G  C  G  G  C
4  T  C  C  TC CT

变成

   P1 P2 o1 o2 o3
1  A  T  a  b  h
2  C  A  b  b  a
3  G  C  a  a  b
4  T  C  b  b  h

其中后代中的 \'a\' 表示它类似于 P1,\'b\' 表示 P2,而 \'h\' 表示两者都有。为了方便起见,我已经将父列从后代中拆分出来(分别为父母和测试),但我的循环不起作用或将整行更改为 NA。我一直在尝试使用以下代码解决重新编码到 \'a\' 和 \'b\' 的问题:

for (i in 1:nrow(Test)) {
  if (Parents[i, 1] == \"A\") {
    Test[Test[i, ] == \"A\"] <- \"a\"
    } else
      if (Parents[i, 2] ==\"A\") {
        Test[Test[i, ] == \"A\"] <-\"b\"
      }
}

我会很感激任何帮助,我拼命地试图避免手工这样做。谢谢你。

    标签: r loops recode


    【解决方案1】:

    我想知道您的预期输出是否与您的规则不一致;假设是这样,试试这个:

    dat
    #   P1 P2 o1 o2 o3
    # 1  A  T  A  T AT
    # 2  C  A CA  A  C
    # 3  G  C  G  G  C
    # 4  T  C  C TC CT
    
    vecgrepl <- Vectorize(grepl)
    dat[,3:5] <- lapply(dat[,3:5], function(Z) 
        sapply(paste0(+(vecgrepl(dat$P1, Z)), +(vecgrepl(dat$P2, Z))),
               switch, "01"="b", "10"="a", "11"="h", "-")
    )
    dat
    #   P1 P2 o1 o2 o3
    # 1  A  T  a  b  h
    # 2  C  A  h  b  a
    # 3  G  C  a  a  b
    # 4  T  C  b  h  h
    

    分解:

    • grepl 只接受长度为 1 的模式,所以我们需要 Vectorize 它。还有其他方法可以达到相同的结果。
    • vecgrepl(dat$P1, Z) 应该返回(对于每一列 Z)是否在其值中找到 P1 的字母。
    • +(.)是将FALSE/TRUE转换为0/1的快捷方式,用于switch下面;诚然,我们可以使用FALSETRUETRUEFALSETRUETRUE 等,我认为这可能看起来更干净。
    • switch 是一种模拟多个 if/then 条件的简单方法,查看三个组合。如果没有看到"01""10""11",则尾随"-" 是默认值(此处为"00")。 (这也可以用dplyr::case_whendata.table::fcase 模拟,只需稍作调整。)
    • 因为switch 也只是长度为1,我使用sapply(..., switch, ...) 对其进行矢量化,其中第二个... 是发送到switch 的参数。等效于sapply(paste0(...), function(x) switch(z, "01"="b", ..))
    • dat[,3:5] &lt;- lapply(dat[,3:5], ..),只对其中三卷执行此操作;也可以完成dat[,-(1:2)] 来完成所有列除了前两个。

    数据

    dat <- structure(list(P1 = c("A", "C", "G", "T"), P2 = c("T", "A", "C", "C"), o1 = c("A", "CA", "G", "C"), o2 = c("T", "A", "G", "TC"), o3 = c("AT", "C", "C", "CT")), class = "data.frame", row.names = c("1", "2", "3", "4"))
    

    【讨论】:

      猜你喜欢
      • 2023-01-19
      • 1970-01-01
      • 2021-10-19
      • 2022-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-27
      • 2019-10-30
      相关资源
      最近更新 更多