【问题标题】:conditionally look up column names to populate new column in r有条件地查找列名以填充 r 中的新列
【发布时间】:2016-10-12 03:43:58
【问题描述】:

我有一个如下所示的 data.frame:

   A C  G T
1  6 0 14 0
2  0 0 20 0
3 14 0  6 0
4 14 0  6 0
5  6 0 14 0

(实际上,我有 1800 个不同数量的行..)

只是为了解释你在看什么: 每行是一个 SNP,因此它可以是一个碱基 (A,C,G,T) 或另一个碱基 (A,C,G,T) SNP1 的主要等位基因是“G”,出现在 14 个个体中,次要等位基因是“A”,出现在数据集中 20 个个体中的 6 个。 SNP1 显示 G 的 14 个个体与 SNP3 显示 A 相同,因此 5 行的碱基组合有两种可能性:一种是 GGAAG,一种是 AGGGA。 这些可以(理论上)由相应行中包含 6 或 14 的所有单元格的列名构建,结果如下:

   A C  G T 14 6
1  6 0 14 0  G A
2  0 0 20 0  G G
3 14 0  6 0  A G
4 14 0  6 0  A G
5  6 0 14 0  G A

有没有一种优雅的方式来实现这样的目标? 我有一段从答案到有点related question 的代码,它将返回矩阵中特定值的位置。

    mat <- matrix(c(1:3), nrow = 4, ncol = 4)
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    1
[2,]    2    3    1    2
[3,]    3    1    2    3
[4,]    1    2    3    1

    find <- function(mat, value) {
      nr <- nrow(mat)
      val_match <- which(mat == value)
      out <- matrix(NA, nrow= length(val_match), ncol= 2)
      out[,2] <- floor(val_match / nr) + 1
      out[,1] <- val_match %% nr
      return(out)
    }

    find(mat, 2)

     [,1] [,2]
[1,]    2    1
[2,]    1    2
[3,]    0    3
[4,]    3    3
[5,]    2    4

我想我可以弄清楚如何将其调整为从原始 data.frame 返回 colname 的位置,但它需要它正在寻找的值作为输入。 – 在一个数据 sn-p 中可能有几个(如上例所示,14 和 6),并且对于我的数据的每个 sn-p,它们是不同的。 在其中一些中,根本没有重复。 此外,如果其中一个值达到 20,则相应的 colname 会自动成为可供选择的值(如上例中的第 2 行所示)。

编辑 我已经尝试了 thelatemail 建议的代码,它在某些数据上运行良好,但并非对所有数据都有效。

例如,这会产生我不完全理解的结果: 子集如下所示:

    A C G T
 1  0 0 3 1
 2  0 9 0 3
 3  3 0 0 2
 4  0 3 0 2
 5  2 0 0 3
 6  0 2 0 3

    sel <- subset > 0
    ord <- order(row(subset)[sel], -subset[sel])
    haplo1 <- split(names(subset)[col(subset)[sel]][ord], row(subset)[sel][ord])

这会产生

 1
 [1] "G" "T"
 2
 [1] "C" "T"
 3
 [1] "A" "T"
 4
 [1] "C" "T"
 5
 [1] "T" "A"
 6
 [1] "T" "C"

由于每行都有一个 3,我不明白为什么这些都不属于这些可能性之一(这将导致 GTACTT 和 TCTTAC 代替)。

我也意识到我有很多缺失的等位基因,只有一两个人被发现在这个基因座上有一个碱基。 可以以某种方式包含“缺失”的列吗? - 我试图添加它,这给了我一个关于不对应行号的错误。

【问题讨论】:

  • 不会有很多其他的可能性 - 例如。 “AGAAA”、“GGAAA”、“AGGAA”……“AAAAA”还是“GGGGG”?
  • 理论上是的。然而,很多 SNP,尤其是靠近在一起时(数据的一个 sn-p 内的所有 SNP 都在 64bp 范围内)是连锁的,这意味着可以构建仅一起出现的等位基因运行(单倍型)。这个特定数据集的美妙之处在于它来自蜜蜂无人机,它们是单倍体(与“正常”的女性二倍体工人/蜂​​王相反),因此每个个体中只有两个可能的主要等位基因之一,我看到的是实际上是在链接中继承的。
  • 为什么要选择基于 3 的基因型?您根据该位点的基因型数量来调用每个位点。第 1 行只有 4 人进行了基因分型,但第 2 行有 12 人进行了基因分型。包括 NA 不会改变选择最频繁和最不频繁等位基因的结果。 R 中有一些关于 bioconductor 的软件包,可以进行您可能想要研究的变体调用和插补。
  • @akaDrHouse,感谢您的意见。抱歉,我之前没有回复,我花了一些时间尝试(再一次)寻找现有的方法来处理这个问题。由于这是通过测序进行基因分型的数据,并且我想与参考基因组进行比对,因此我的选择有些有限,并且没有包括构建这些……局部单倍型。到目前为止,我还没有找到能满足我所有条件的东西,这就是为什么我让自己尝试自己做这件事,尽管很粗糙。 ;)
  • @akaDrHouse 再次:我试图将相同数量的碱基计数保持在一起,因为基因分型的个体是单倍体蜜蜂无人机,它们经过纯化选择,这意味着某些单倍型是不可行的在无人机中,总体人群中的主要和次要等位基因偏斜。 - 除此之外,如果将所有数字按顺序排列,我根本不明白所有 3 怎么不会出现在一列中。

标签: r


【解决方案1】:

为了让我的最小功能正常工作,我不得不将零转换为 NA。出于某种原因,na.rm=TRUE 不适用于 which.min

看看这对你有没有帮助:

A <- c(6,0,14,14,6)
C <- c(0,0,0,0,0)
G <- c(14,20,6,6,14)
T <- c(0,0,0,0,0)
mymatrix <- as.matrix(cbind(A,C,G,T))
mymatrix<-ifelse(mymatrix==0,mymatrix==NA,mymatrix)
mymatrix

major_allele <- colnames(mymatrix)[apply(mymatrix,1,which.max)] ; head(major_allele)
minor_allele <- colnames(mymatrix)[apply(mymatrix,1,which.min)] ; head(minor_allele)

myds<-as.data.frame(cbind(mymatrix,major_allele,minor_allele))
myds


> myds
     A    C  G    T major_allele minor_allele
1    6 <NA> 14 <NA>            G            A
2 <NA> <NA> 20 <NA>            G            G
3   14 <NA>  6 <NA>            A            G
4   14 <NA>  6 <NA>            A            G
5    6 <NA> 14 <NA>            G            A

【讨论】:

    【解决方案2】:

    无论每行有多少点击,这里都有一个尝试。它返回一个列表对象,这可能适用于每行不同长度的结果。

    sel <- dat > 0
    ord <- order(row(dat)[sel], -dat[sel])
    split(names(dat)[col(dat)[sel]][ord], row(dat)[sel][ord] )
    #List of 5
    # $ 1: chr [1:2] "G" "A"
    # $ 2: chr "G"
    # $ 3: chr [1:2] "A" "G"
    # $ 4: chr [1:2] "A" "G"
    # $ 5: chr [1:2] "G" "A"
    

    dat 在哪里:

    dat <- read.table(text="
       A C  G T
    1  6 0 14 0
    2  0 0 20 0
    3 14 0  6 0
    4 14 0  6 0
    5  6 0 14 0
    ", header=TRUE)
    

    【讨论】:

    • 非常感谢。我花了一段时间才弄清楚这个拆分到底做了什么,但不幸的是,我在另一个 sn-p 数据上尝试了它,它没有返回相同的结果,我真的不知道为什么。 A C G T 1 0 0 3 1 2 0 9 0 3 3 3 0 0 2 4 0 3 0 2 5 2 0 0 3 6 0 2 0 3
    • 啊。对此感到抱歉。我已将新数据示例和产生的问题添加到原始问题中。
    • @GertjePetersen - 假设您在 cmets 中的数据从 1... 6 开始分成几行,我可以让我的代码按上述方式工作。
    • 可以的,我上面已经加了。
    • @GertjePetersen - 我的代码所做的就是将每行中的 >0 个单元格按从大到小的顺序排列。我不确定输出应该如何得到你的 2 套。我对生物化学一无所知,所以我可能忽略了这种排序是如何发生的。
    猜你喜欢
    • 2020-05-08
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 2017-01-08
    • 1970-01-01
    • 2017-07-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多