R - 按列比较两行并将结果写入 table

R - comparing two rows by columns and writing the result in a table

我是 R 新手,我的问题的解决方案可能非常简单,但目前我无法解决... 我想按列比较数据框中的行。每列数据为一个字母(核苷酸碱基):

seq1 A C T G T
seq2 A C G G G
seq3 A G G C A
...

我想按列比较数据集中的所有行。我想得到的结果是比较简单的 1 或 0 表示 TRUE 和 FALSE,同样写成 table 的形式。所以它看起来像这样:

seq1_seq2 1 1 0 1 0
seq1_seq3 1 0 0 0 0
seq2_seq3 1 0 1 0 0
...

我的 R 技能太低,写不出有用的东西。然而,我设法发现

ifelse(data[1,]==data[2,], 1, 0) 

returns 几乎是我需要的,尽管没有显示比较了哪些行(没有 seq1_seq2 列)。 对于这个问题,我将不胜感激。当然,最需要一个完整解决方案的示例,但我也将非常感谢有关如何解决此问题的任何建议。

提前致谢!

在这种情况下,由于您希望完成所有 n 平方比较,因此以这种方式循环是一种选择:

result <- list()
for (i in 1:(nrow(df) - 1)) {
    for (j in (i + 1):nrow(df)) {
      result[[paste(row.names(df)[i], row.names(df)[j], sep = '_')]] <- as.integer(df[i, ] == df[j, ])
    }
}
as.data.frame(do.call(rbind, result))

结果输出如下:

          V1 V2 V3 V4 V5
seq1_seq2  1  1  0  1  0
seq1_seq3  1  0  0  0  0
seq2_seq3  1  0  1  0  0

当然,对于较大的数据集,这会很慢。

与 Gopala 的方法有些不同...可能有更简单的方法,但这里是:

options(stringsAsFactors = FALSE)
myData <- data.frame(n1=c("A","A","A"),n2=c("C","C","G"),
                     n3=c("T","G","G"),n4=c("G","G","C"),n5=c("T","G","A"))
rownames(myData) <- paste0("seq",1:3)

# Generate all combinations for comparisons
compar <- apply(combn(rownames(myData),2),2,paste0)

# Create a temporary list having pairs of rows
myList <- apply(compar, 2, function(r) myData[r,])
names(myList) <- apply(combn(rownames(myData),2),2,paste0,collapse="_")

# Compare the two rows for each element in the list
results <- t(sapply(myList, function(x) as.numeric(x[1,]==x[2,])))
colnames(results) <- colnames(myData)

results

          n1 n2 n3 n4 n5
seq1_seq2  1  1  0  1  0
seq1_seq3  1  0  0  0  0
seq2_seq3  1  0  1  0  0

按行在数据框中存储序列是错误的。您应该按列存储序列,或者,如果按行存储它们,至少在矩阵而不是数据框中进行。下面我假设你使用矩阵。您可以使用 as.matrix 函数将数据帧转换为矩阵。

如果你想避免循环,你应该使用 combn 来完成这样的任务

> a
     [,1] [,2] [,3] [,4] [,5]
seq1 "A"  "C"  "T"  "G"  "T" 
seq2 "A"  "C"  "G"  "G"  "G" 
seq3 "A"  "G"  "G"  "C"  "A" 

> compare = t(combn(nrow(a),2,FUN=function(x)a[x[1],]==a[x[2],]))
> rownames(compare) = combn(nrow(a),2,FUN=function(x)paste0("seq",x[1],"_seq",x[2]))

> compare
          [,1]  [,2]  [,3]  [,4]  [,5]
seq1_seq2 TRUE  TRUE FALSE  TRUE FALSE
seq1_seq3 TRUE FALSE FALSE FALSE FALSE
seq2_seq3 TRUE FALSE  TRUE FALSE FALSE

将布尔值转换为整数(如果您确实需要):

storage.mode(compare) = "integer"

您可以使用此代码(它使用@Dominic Comtois 的回答中的myData):

m <- combn(nrow(myData),2)

result <- sapply(myData,function(C) {z=C[m];z[c(TRUE,FALSE)]==z[c(FALSE,TRUE)]})
#       n1    n2    n3    n4    n5
#[1,] TRUE  TRUE FALSE  TRUE FALSE
#[2,] TRUE FALSE FALSE FALSE FALSE
#[3,] TRUE FALSE  TRUE FALSE FALSE

工作原理:

  1. combn 生成所有可能的行索引对
  2. sapply 遍历 myData
  3. 的每一列
  4. 对于每一列,获取矩阵 m 的向量模拟,其中行索引由 myData
  5. 中的值代替
  6. 这个向量的奇数元素包含第一行,偶数元素包含第二行,因此我们可以使用位掩码 c(TRUE,FALSE) 和 c(FALSE,TRUE) 来比较 odd/even 个元素.