将 NA 行替换为前一行和特定列中的非 NA 值

问题描述 投票:0回答:4

我有一个矩阵,其中行的所有列都可以有 NA。我想用前一行的非 NA 值和第 K 列替换这些 NA 行。

例如这个矩阵:

      [,1] [,2]
 [1,]   NA   NA
 [2,]   NA   NA
 [3,]    1    2
 [4,]    2    3
 [5,]   NA   NA
 [6,]   NA   NA
 [7,]   NA   NA
 [8,]    6    7
 [9,]    7    8
[10,]    8    9

必须转换为这个非 NA 矩阵,我们使用第 2 列进行替换:

      [,1] [,2]
 [1,]   NA   NA
 [2,]   NA   NA
 [3,]    1    2
 [4,]    2    3
 [5,]    3    3
 [6,]    3    3
 [7,]    3    3
 [8,]    6    7
 [9,]    7    8
[10,]    8    9

我为此编写了一个函数,但使用了循环:

# replaces rows which contains all NAs with non-NA values from previous row and K-th column
na.replace <- function(x, k) {
    cols <- ncol(x)
    for (i in 2:nrow(x)) {
        if (sum(is.na(x[i - 1, ])) == 0 && sum(is.na(x[i, ])) == cols) {
            x[i, ] <- x[i - 1 , k]
        }
    }
    x
}

似乎这个函数工作正常,但我想避免这些循环。谁能建议我如何在不使用循环的情况下进行此替换?

更新

agstudy建议它自己的矢量化非循环解决方案:

na.replace <- function(mat, k){
  idx       <-  which(rowSums(is.na(mat)) == ncol(mat))
  mat[idx,] <- mat[ifelse(idx > 1, idx-1, 1), k]
  mat
}

但是与我的循环解决方案相比,这个解决方案返回了不同且错误的结果。为什么会出现这种情况?理论上循环和非循环解决方案是相同的。

r na
4个回答
5
投票

试试这个功能。我们可以在向量中的任何位置替换 NA

NA.replace <-function(x) {
       i <- cumprod(is.na(x))
       x[!!i] <- x[which.min(i)]
        if (length(x) > 0L) {
            non.na.idx <- which(!is.na(x))
            if (is.na(x[1L])) {
                non.na.idx <- c(1L, non.na.idx)
            }
            rep.int(x[non.na.idx], diff(c(non.na.idx, length(x) + 1L)))
        }  
}

NA.replace(c(NA, 1, 2, NA, NA, 3, NA, NA, 4, NA))

# [1] 1 1 2 2 2 3 3 3 4 4

2
投票

编辑:我完全改变了基于 na.locf 的第一个解决方案是

这里有一个新的矢量化解决方案:

idx <- which(rowSums(is.na(mat)) == ncol(mat))
mat[idx,1:2]= mat[ifelse(idx>1,idx-1,1),2]

     X..1. X..2.
[1,]     NA    NA
[2,]     NA    NA
[3,]      1     2
[4,]      2     3
[5,]      3     3
[6,]      4     5
[7,]      5     5
[8,]      6     7
[9,]      7     8
[10,]     8     9

您可以将其包装在一个函数中:

function(mat,k){
  idx       <-  which(rowSums(is.na(mat)) == ncol(mat))
  mat[idx,] <- mat[ifelse(idx>1,idx-1,1),k]
}

2
投票

I' sete n.lc`fncininalo ha ipl se he ex 列来生成向量或 rplcmntvlus Hwve,tismy ob ey fiieti 你的矩阵很大。

library()

m -cbnd(
    cN, A ,2,N, ,N,6,7 ),
   c(A,N, ,3,NA ,NA , ,9)
)

m,nclm) - a.ofm[ no()] armFLE)

fo ( nsq(co(m-1,1) {
    rplceet_aue  n.ocfm, +],n.mFASE)
   misn([,i],i]< rplcmntvaus[s.a([ ])  

0
投票

终于实现了我自己的矢量化版本。它返回预期输出:

na.replace <- function(x, k) {
    isNA <- is.na(x[, k])
    x[isNA, ] <- na.locf(x[, k], na.rm = F)[isNA]
    x
}

更新

更好的解决方案,无需任何软件包

na.lomf <- function(x) {
    if (length(x) > 0L) {
        non.na.idx <- which(!is.na(x))
        if (is.na(x[1L])) {
            non.na.idx <- c(1L, non.na.idx)
        }
        rep.int(x[non.na.idx], diff(c(non.na.idx, length(x) + 1L)))
    }
}

na.lomf(c(NA, 1, 2, NA, NA, 3, NA, NA, 4, NA))
# [1] NA  1  2  2  2  3  3  3  4  4
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.