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
工作原理:
combn
生成所有可能的行索引对
sapply
遍历 myData
的每一列
- 对于每一列,获取矩阵
m
的向量模拟,其中行索引由 myData
中的值代替
- 这个向量的奇数元素包含第一行,偶数元素包含第二行,因此我们可以使用位掩码 c(TRUE,FALSE) 和 c(FALSE,TRUE) 来比较 odd/even 个元素.
我是 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
工作原理:
combn
生成所有可能的行索引对sapply
遍历myData
的每一列
- 对于每一列,获取矩阵
m
的向量模拟,其中行索引由myData
中的值代替
- 这个向量的奇数元素包含第一行,偶数元素包含第二行,因此我们可以使用位掩码 c(TRUE,FALSE) 和 c(FALSE,TRUE) 来比较 odd/even 个元素.