【问题标题】:Find the index position of the first non-NA value in an R vector?找到 R 向量中第一个非 NA 值的索引位置?
【发布时间】:2011-10-12 02:59:35
【问题描述】:

我有一个问题,一个向量在开始时有一堆 NA,然后是数据。然而,我的数据的特点是前 n 个非 NA 值可能不可靠,所以我想删除它们并用 NA 替换它们。

例如,如果我有一个长度为 20 的向量,并且非 NA 从索引位置 4 开始:

> z
 [1]          NA          NA          NA -1.64801942 -0.57209233  0.65137286  0.13324344 -2.28339326
 [9]  1.29968050  0.10420776  0.54140323  0.64418164 -1.00949072 -1.16504423  1.33588892  1.63253646
[17]  2.41181291  0.38499825 -0.04869589  0.04798073

我想删除我认为不可靠的前 3 个非 NA 值,以便给出:

> z
 [1]          NA          NA          NA          NA          NA          NA  0.13324344 -2.28339326
 [9]  1.29968050  0.10420776  0.54140323  0.64418164 -1.00949072 -1.16504423  1.33588892  1.63253646
[17]  2.41181291  0.38499825 -0.04869589  0.04798073

当然,我需要一个通用的解决方案,但我永远不知道第一个非 NA 值何时开始。我该怎么做呢? IE如何找出第一个非NA值的索引位置?

为了完整起见,我的数据实际上排列在一个数据框中,列中有很多这些向量,每个向量可以有不同的非 NA 起始位置。此外,一旦数据开始,可能会有零星的 NA 进一步向下,这使我无法简单地计算它们的数量,作为解决方案。

【问题讨论】:

  • 有没有一种有效的方法可以在找到第一个时停止搜索?

标签: r


【解决方案1】:

使用is.nawhich 的组合来查找非NA 索引位置。

NonNAindex <- which(!is.na(z))
firstNonNA <- min(NonNAindex)

# set the next 3 observations to NA
is.na(z) <- seq(firstNonNA, length.out=3)

【讨论】:

  • 当,这是我的第二个猜测。想看中rle(),但我更喜欢这个解决方案。
  • 非常感谢。经过一番思考,我想出了 min((1:length(z))[!is.na(z)]),但当然这个想法要好得多。完美
  • firstNonNA &lt;- NonNAindex[1] 更快吗?我会在使用[1]min() 时遇到一些问题吗?
  • @FlorianJenn:是的,这可能会更快,尤其是对于较大的向量。我无法立即想到在min 上使用它的问题。
  • 对于那些只想删除所有 NA 的人(与这个问题的要求有点不同):x &lt;- c(NA, "B", "C", "D"); x[!is.na(x)]
【解决方案2】:

与@Joshua 的想法类似,但使用which.min()

## dummy data
set.seed(1)
dat <- runif(10)
dat[seq_len(sample(10, 1))] <- NA

## start of data
start <- which.min(is.na(dat))

给出:

> (start <- which.min(is.na(dat)))
[1] 4

使用它来将start:(start+2) 设置为NA

is.na(dat) <- seq(start, length.out = 3)

导致:

> dat
 [1]         NA         NA         NA         NA         NA
 [6]         NA 0.94467527 0.66079779 0.62911404 0.06178627

【讨论】:

  • 更干净。谢谢,也感谢您继续回答。
  • +1,但我不确定清洁剂。它更短,但对于没有意识到 which.minTRUEFALSE 分别强制转换为 10 的人来说可能不太清楚。
  • @Joshua 同意,它还依赖于 which.min 返回任何绑定最小值中的第一个的行为。不确定更短是否值得接受。
  • 这个似乎很难处理 NA 后面跟着非 NA 的情况,而不是到处都有 NA。返回的索引不适用。 Joshua 详述的解决方案按预期工作。
  • @MatteoCastagna 这适用于 OP 示例和 Q,其中 NAs 位于向量的前面。正如我在 cmets 中提到的,这依赖于 which.min() 的行为,这正是它在您描述的情况下失败的原因。
【解决方案3】:

如果处理大数据,Positionwhich 快得多,因为它只评估直到找到匹配项,而不是评估整个向量。

x=c(rep(NA,3),1:1e8)
Position(function(x) !is.na(x), x)
# 4

我们可以将 NA 分配给后面的 N 个值(或向量的末尾,以先到者为准)

pos = Position(function(x)!is.na(x), x)
x[pos:min(pos+N-1, length(x))] <- NA

【讨论】:

  • 这在大数据上表现良好
  • 无需定义新函数,可以使用complete.cases
【解决方案4】:

我会按照以下方式做一些事情

# generate some data
tb <- runif(10)
tb[1:3] <- NA

# I convert vector to TRUE/FALSE based on whether it's NA or not
# rle function will tell you when something "changes" in the vector
# (in our case from TRUE to FALSE)
tb.rle <- rle(is.na(tb))

# this is where vector goes from all TRUE to (at least one) FALSE
# your first true number is one position ahead, so +1
tb.rle$lengths[1] 

# you can now subset your vector with the first non-NA value
# and do with it whatever you want. I assign it a fantastic 
# non-believable number
tb[tb.rle$lengths[1] + 1] <- 42

【讨论】:

    【解决方案5】:
    zoo 包中的

    na.trim() 可以提供帮助。

    library(zoo)
    dummy.data <- c(rep(NA, 5), seq(1:7), NA)
    x <- length(dummy.data) - length(na.trim(dummy.data, sides = "left"))
    dummy.data[(x+1):(x+3)] <- NA
    dummy.data
    [1] NA NA NA NA NA NA NA NA  4  5  6  7 NA
    

    【讨论】:

      【解决方案6】:

      你也可以直接使用replace()函数,我知道答案已经有了,但是像replace()这样的东西太好用了

      例如-:

      A <- c(1,2,3,4,5,NA,58,NA,98,NA,NA,NA)
      which(is.na(A))
      A <- replace(A,1:3,NA)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多