使用r创建同现矩阵

时间:2019-11-26 15:37:39

标签: r dataframe matrix rbind

我想为以下数据(随机生成)建立一个共现矩阵:

         OTU1 OTU2 OTU3 OTU4 .... OTU598
patient1  0    1    1    0        1    
patient2  1    0    1    0        1 
.
.
.
patient143 1   0    1    1         1

我想用三列创建一个共同出现矩阵,如下所示:(一名患者): 首先考虑otu并与所有其他OTU进行比较。如果两个OTU(例如:OTU1和OTU2)具有1,那么我想创建一个称为counts的列并放入1。

otu1    otu2    counts
OTU1    OTU2      0
OTU1    OTU3      0
OTU1    OTU4      0
OTU2    OTU1      0
OTU2    OTU3      1

所以我尝试了以下代码:

a <- apply(bin_OTU_tab,1,function(row_val) lapply(1:ncol(bin_OTU_tab), 
                                              function(i){ lapply(i:ncol(bin_OTU_tab),
                                                                  function(j){if(bin_OTU_tab[row_val,i] == 1&&bin_OTU_tab[row_val,j] == 1){return(1) }else{return(0)
                                                                    }})}))

它是矩阵格式。我想将此矩阵更改为数据帧,并按所需的输出进行排列(如上所述)。我希望rbind可以工作吗?但是无法理解如何从这里继续。 有人可以在这方面指导我吗?

2 个答案:

答案 0 :(得分:1)

这给出了一个矩阵列表,每个病人一个:

# fake data
set.seed(47)
m = matrix(round(runif(15)), nrow = 3)
colnames(m) = paste0("OTU", 1:ncol(m))
m
#      OTU1 OTU2 OTU3 OTU4 OTU5
# [1,]    1    1    0    1    0
# [2,]    0    1    0    0    1
# [3,]    1    1    1    1    1

template = as.data.frame(t(combn(colnames(m), 2)))
names(template) = c("otu1", "otu2")
template$counts = 0

result = apply(m, 1, function(x) {
  ones = names(x)[x == 1]
  result = template
  result[result$otu1 %in% ones & result$otu2 %in% ones, "counts"] = 1 
  return(result)
})

result
# [[1]]
#    otu1 otu2 counts
# 1  OTU1 OTU2      1
# 2  OTU1 OTU3      0
# 3  OTU1 OTU4      1
# 4  OTU1 OTU5      0
# 5  OTU2 OTU3      0
# 6  OTU2 OTU4      1
# 7  OTU2 OTU5      0
# 8  OTU3 OTU4      0
# 9  OTU3 OTU5      0
# 10 OTU4 OTU5      0
# 
# [[2]]
#    otu1 otu2 counts
# 1  OTU1 OTU2      0
# 2  OTU1 OTU3      0
# 3  OTU1 OTU4      0
# 4  OTU1 OTU5      0
# 5  OTU2 OTU3      0
# 6  OTU2 OTU4      0
# 7  OTU2 OTU5      1
# 8  OTU3 OTU4      0
# 9  OTU3 OTU5      0
# 10 OTU4 OTU5      0
# 
# [[3]]
#    otu1 otu2 counts
# 1  OTU1 OTU2      1
# 2  OTU1 OTU3      1
# 3  OTU1 OTU4      1
# 4  OTU1 OTU5      1
# 5  OTU2 OTU3      1
# 6  OTU2 OTU4      1
# 7  OTU2 OTU5      1
# 8  OTU3 OTU4      1
# 9  OTU3 OTU5      1
# 10 OTU4 OTU5      1

答案 1 :(得分:0)

如果您使用的是base R,那么下面的代码可能就是您想要的

l <- apply(m, 1, function(v) 
  setNames(data.frame(cbind(t(combn(colnames(m),2)),(M <- outer(v,v,"*"))[lower.tri(M)])), 
           c("otu1","otu2","counts")))

屈服

> l
$patient1
   otu1 otu2 counts
1  OTU1 OTU2      0
2  OTU1 OTU3      0
3  OTU1 OTU4      0
4  OTU1 OTU5      0
5  OTU2 OTU3      0
6  OTU2 OTU4      0
7  OTU2 OTU5      0
8  OTU3 OTU4      0
9  OTU3 OTU5      0
10 OTU4 OTU5      1

$patient2
   otu1 otu2 counts
1  OTU1 OTU2      0
2  OTU1 OTU3      0
3  OTU1 OTU4      0
4  OTU1 OTU5      0
5  OTU2 OTU3      0
6  OTU2 OTU4      0
7  OTU2 OTU5      0
8  OTU3 OTU4      0
9  OTU3 OTU5      0
10 OTU4 OTU5      0

$patient3
   otu1 otu2 counts
1  OTU1 OTU2      0
2  OTU1 OTU3      0
3  OTU1 OTU4      0
4  OTU1 OTU5      0
5  OTU2 OTU3      1
6  OTU2 OTU4      1
7  OTU2 OTU5      0
8  OTU3 OTU4      1
9  OTU3 OTU5      0
10 OTU4 OTU5      0

$patient4
   otu1 otu2 counts
1  OTU1 OTU2      1
2  OTU1 OTU3      1
3  OTU1 OTU4      0
4  OTU1 OTU5      0
5  OTU2 OTU3      1
6  OTU2 OTU4      0
7  OTU2 OTU5      0
8  OTU3 OTU4      0
9  OTU3 OTU5      0
10 OTU4 OTU5      0

数据

m <- structure(c(0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 
0, 0, 0), .Dim = 4:5, .Dimnames = list(c("patient1", "patient2", 
"patient3", "patient4"), c("OTU1", "OTU2", "OTU3", "OTU4", "OTU5"
)))