【问题标题】:Fill missing values in a matrix with values from different rows in that matrix in R用R中该矩阵中不同行的值填充矩阵中的缺失值
【发布时间】:2020-10-27 17:18:41
【问题描述】:

我有一个包含核苷酸序列(包含 NA)的矩阵,如下所示:

n.mat

samp1 <- c("a","c","a",NA,"t","c")
samp2 <- c("a","c","t","t",NA,"a")
samp3 <- c("a","g","g","c","a","c")
samp4 <- c("a","g",NA,"g","g", NA)
samp5<- c(NA, "g","g","g","t","g")

n.mat <- rbind(samp1,samp2,samp3,samp4,samp5)

      [,1] [,2] [,3] [,4] [,5] [,6]
samp1 "a"  "c"  "a"   NA  "t"  "c" 
samp2 "a"  "c"  "t"  "t"   NA  "a" 
samp3 "a"  "g"  "g"  "c"  "a"  "a" 
samp4 "a"  "g"   NA  "g"  "g"   NA 
samp5  NA  "g"  "g"  "g"  "t"  "g" 

我还有一个包含序列名称的两列数据框:

df

df <- data.frame(
  X1 = c("samp1", "samp2", "samp3", "samp4", "samp5"),
  X2 = c("samp2", "samp5", "samp1", "samp3", "samp2"))

          X1       X2
1      samp1    samp2
2      samp2    samp5
3      samp3    samp1
4      samp4    samp3
5      samp5    samp2

我想用数据框中df$X2 列指示的矩阵中另一行的核苷酸/值填充矩阵中一行的空白。

例如:矩阵中的samp1 在第四列的行中有一个NA。所以我想从samp2 中取出同一列中的字符串(由X2 列中的数据框表示)。对于samp2,我想通过从samp5 获取字符串来填充NA(由X2 列中的数据框指示)。 如果行中没有NAsamp3 一样,则什么也不做。 如果一行中有两个NAs(就像在samp4 中一样),那么我想从samp3 两列中获取两个字符串。

我尝试了以下代码:

replace.na <- function(n.mat,val) {
  i <- is.na(n.mat)
  j <- which(i)
  k <- which(!i)
  n.mat[j[j > k[length(k)]]] <- val
  n.mat
}

n.mat[,-1] <- t(apply(matrix[,-1],1,replace.na)) 

但我不太确定如何包含 df 表来替换 NAs

【问题讨论】:

    标签: r matrix


    【解决方案1】:

    下面是我将解释的一些非常紧凑的代码(假设使用 R v 4.x 或使用 stringsAsFactors=FALSE 创建“df”数据框):

    n.mat[ is.na(n.mat) ] <-  n.mat[df[['X2']],][ is.na(n.mat)]
    
    n.mat
    #------
          [,1] [,2] [,3] [,4] [,5] [,6]
    samp1 "a"  "c"  "a"  "t"  "t"  "c" 
    samp2 "a"  "c"  "t"  "t"  "t"  "a" 
    samp3 "a"  "g"  "g"  "c"  "a"  "a" 
    samp4 "a"  "g"  "g"  "g"  "g"  "a" 
    samp5 "a"  "g"  "g"  "g"  "t"  "g" 
    

    is.na(.n.mat) 返回一个与 n.mat 维数相同的逻辑矩阵。它被用作分配两侧的索引,但分配的右侧是从一个矩阵中挑选的,该矩阵的行按您在df 中指定的“替换行”的顺序重新排列。如果“X1”列的顺序与目标矩阵的顺序不同,则需要通过order 调用对该列重新排序,但此处不需要。

     df <- read.table(text= 'X1       X2
     1      samp1    samp2
     2      samp2    samp5
     3      samp3    samp1
     4      samp4    samp3
     5      samp5    samp2', header=TRUE, stringsAsFactors=FALSE)
    

    注意stringsAsFactors=FALSE。我认为我没有使用它(因为我仍在使用 R 3.6 意味着我在 X2 列中有因素。

    另一种方法是创建一个包含 NA 位置的两列索引,并将 arr.idx 参数设置为 TRUE:

     pos <- which(is.na(n.mat),arr.ind=TRUE)
    
    > pos
          row col
    samp5   5   1
    samp4   4   3
    samp1   1   4
    samp2   2   5
    samp4   4   6
    

    然后您可以使用该 2 列矩阵进行索引:

     n.mat[pos] <- n.mat[ df[['X2']] ,][pos]
    
    > n.mat
          [,1] [,2] [,3] [,4] [,5] [,6]
    samp1 "a"  "c"  "a"  "t"  "t"  "c" 
    samp2 "a"  "c"  "t"  "t"  "t"  "a" 
    samp3 "a"  "g"  "g"  "c"  "a"  "a" 
    samp4 "a"  "g"  "g"  "g"  "g"  "a" 
    samp5 "a"  "g"  "g"  "g"  "t"  "g" 
    

    R 的矩阵索引可以为此类问题产生一些非常紧凑的解决方案。您应该考虑阅读?'[' 帮助页面以获取更多详细信息和示例。如果您继续使用 R,您所付出的努力将得到多次回报。我相信我现在已经阅读了 10 或 20 次。

    代表:

    n.mat <- matrix( scan(text = 'samp1 "a"  "c"  "a"  "NA" "t"  "c" 
     samp2 "a"  "c"  "t"  "t"  "NA" "a" 
     samp3 "a"  "g"  "g"  "c"  "a"  "a" 
     samp4 "a"  "g"  "NA" "g"  "g"  "NA" 
     samp5 "NA" "g"  "g"  "g"  "t"  "g" ', what=""), nrow=5, byrow=TRUE)
    
     n.mat <- matrix(n.mat[ ,-1], nrow=5, dimnames=list(n.mat[,1], NULL))
    
    df <- read.table(text= 'X1       X2
     1      samp1    samp2
     2      samp2    samp5
     3      samp3    samp1
     4      samp4    samp3
     5      samp5    samp2', header=TRUE, stringsAsFactors=FALSE)
    

    【讨论】:

    • 您好,非常感谢,我认为您的想法很有帮助,如果没有重复,效果会很好。但我认为矩阵第二行第五列的NA 没有正确转换。它应该是t。我还在检查NAs 的不同排列,然后它不会转换每个NA。您是否还有其他选择?
    • 代码是正确的(我认为),但我怀疑我们俩都在使用 R 3.6 或更低版本,并接受默认的 stringsAsFactors 创建 data.frame。一行中的多个 NA 应该没有问题。如果 df 替换表中的 n.mat 矩阵的特定行没有条目,则可能会出现问题。在这种情况下,您应该放置一个带有一行引用自身的占位符。例如3 sampx sampx
    【解决方案2】:

    您可以尝试以下类似的方法。请注意,输出有点不同,但我复制/粘贴了您创建矩阵的代码(请参阅samp3 第 6 列)。

    t(sapply(rownames(n.mat), function(x) {
      na_cols <- is.na(n.mat[x, ])
      n.mat[x, na_cols] <- n.mat[df[df$X1 == x, "X2"], na_cols]
      n.mat[x, ]
    }))
    

    输出

          [,1] [,2] [,3] [,4] [,5] [,6]
    samp1 "a"  "c"  "a"  "t"  "t"  "c" 
    samp2 "a"  "c"  "t"  "t"  "t"  "a" 
    samp3 "a"  "g"  "g"  "c"  "a"  "c" 
    samp4 "a"  "g"  "g"  "g"  "g"  "c" 
    samp5 "a"  "g"  "g"  "g"  "t"  "g" 
    

    数据

    n.mat <- structure(c("a", "a", "a", "a", NA, "c", "c", "g", "g", "g", 
    "a", "t", "g", NA, "g", NA, "t", "c", "g", "g", "t", NA, "a", 
    "g", "t", "c", "a", "c", NA, "g"), .Dim = 5:6, .Dimnames = list(
        c("samp1", "samp2", "samp3", "samp4", "samp5"), NULL))
    

    【讨论】:

    • 检查你的结果,看看你的 df$X2 是否是一个因素。
    • 我的 df$X2 不是一个因素,只是一个字符向量(我使用的是 R 4.0.2,可能已经习惯了 stringsAsFactors 作为默认的 FALSE)...顺便说一句,我喜欢你的简洁代码/答案...
    • 我得到了不同的结果。查看第 6 列,第 3 行和第 4 行。
    • 嗯...我得到了与您的答案相同的结果。我想知道这是否可能是由于n.mat 数据的差异。 OP 示例数据可能已更改 - samp3 向量以“c”结尾 - 但在 rbind 之后,n.mat 矩阵的行 samp3 col 6 为“a”。我会将示例数据添加到我的答案中(虽然很想删除,但不确定它有多大用处)。
    • 你是对的。 OP更改了示例并没有告诉我们。我用的是原来的问题。
    猜你喜欢
    • 2021-01-15
    • 1970-01-01
    • 2020-07-09
    • 2015-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    • 1970-01-01
    相关资源
    最近更新 更多