R:在数据框中:将列中的第一个非 NA 值设置为 NA

R: In dataframe: set first non-NA value in column to NA

我有一个大型数据框,包含 300 多列(时间序列)和大约 2600 个观察值。这些列充满了很多 NA,然后是一个很短的时间序列,然后通常又是 NA。我想在每列中找到第一个非 NA 值并将其替换为 NA。

这就是我希望实现的目标,只是使用更大的数据框:

之前:

   x1 x2 x3 x4
1  NA NA NA NA
2  NA NA NA NA
3   1  1 NA NA
4   2  2  1  1
5   3  3  2  2
6   4  4  3  3
7   5  5  4  4
8   6  6  5  5
9   7  7  6  6
10  8  8  7  7
11  9  9 NA NA
12 10 10 NA NA
13 NA NA NA NA
14 NA NA NA NA

之后:

   x1 x2 x3 x4
1  NA NA NA NA
2  NA NA NA NA
3  NA NA NA NA
4   2  2 NA NA
5   3  3  2  2
6   4  4  3  3
7   5  5  4  4
8   6  6  5  5
9   7  7  6  6
10  8  8  7  7
11  9  9 NA NA
12 10 10 NA NA
13 NA NA NA NA
14 NA NA NA NA

我四处搜索并找到了对每一列执行此操作的方法,但事实证明我很难将其应用于整个数据框。

我创建了一个示例数据框来重现我的原始数据框:

#Dataframe with NA
x1=x2=c(NA,NA,1:10,NA,NA)
x3=x4=c(NA,NA,NA,1:7,NA,NA,NA,NA)
df=data.frame(x1,x2,x3,x4)

我已经用它在 1 列中用 NA 替换了第一个值(由@Joshua Ulrich here 提供),但是我想将它应用于所有列而无需手动更改 300 多个代码:

NonNAindex <- which(!is.na(df[,1]))
firstNonNA <- min(NonNAindex)
is.na(df[,1]) <- seq(firstNonNA, length.out=1)

我试图将上面的设置为一个函数,并且 运行 它用于所有具有 apply/lapply 的列,以及一个 for 循环,但是还没有真正弄清楚如何将更改应用到我的数据框。我确定有些事情我完全忽略了,因为我只是在 R 中迈出了我的第一步。

非常感谢所有建议!

由于您想对所有列执行此操作,因此可以使用 dplyr 中的 mutate_all 函数。参见 http://dplyr.tidyverse.org/ for more information. In particular, you may want to look at some of the examples shown here

library(dplyr)
mutate_all(df, funs(if_else(row_number() == min(which(!is.na(.))), NA_integer_, .)))
#>    x1 x2 x3 x4
#> 1  NA NA NA NA
#> 2  NA NA NA NA
#> 3  NA NA NA NA
#> 4   2  2 NA NA
#> 5   3  3  2  2
#> 6   4  4  3  3
#> 7   5  5  4  4
#> 8   6  6  5  5
#> 9   7  7  6  6
#> 10  8  8  7  7
#> 11  9  9 NA NA
#> 12 10 10 NA NA
#> 13 NA NA NA NA
#> 14 NA NA NA NA

我们可以使用base R

df1[] <- lapply(df1, function(x) replace(x, which(!is.na(x))[1], NA))
df1
#   x1 x2 x3 x4
#1  NA NA NA NA
#2  NA NA NA NA
#3  NA NA NA NA
#4   2  2 NA NA
#5   3  3  2  2
#6   4  4  3  3
#7   5  5  4  4
#8   6  6  5  5
#9   7  7  6  6
#10  8  8  7  7
#11  9  9 NA NA
#12 10 10 NA NA
#13 NA NA NA NA
#14 NA NA NA NA

或者按照@thelatemail 的建议

df1[] <- lapply(df1, function(x) replace(x, Position(Negate(is.na), x), NA))