从变化列开始替换数据帧中的NA值

时间:2017-02-23 13:52:39

标签: r dataframe fill na

这是NA主题的一个变种,我无法找到答案。我按列进行月度观察,逐行排列。一些缺失值是真实的,但有些值应为零。我想用零替换给定系列的缺失值,但仅在观察到该系列的值之后。

例如,给定:

   Mth1 Mth2 Mth3 Mth4
1    1    2    1    3
2    NA   3    2    1
3    NA   2    1   NA
4    NA   NA   2   NA
5    2    2    NA   2

我想将其更改为:

   Mth1 Mth2 Mth3 Mth4
1    1    2    1    3
2    NA   3    2    1
3    NA   2    1    0
4    NA   NA   2    0
5    2    2    0    2

我想要像locf这样的函数,它能够在第一次正面观察之前留下缺失的值,但我想用零填充而不是使用最后一次观察。

2 个答案:

答案 0 :(得分:3)

这是使用矩阵索引的另一个基本R方法:

df[is.na(df) & t(apply(!is.na(df), 1, cummax))] <- 0
df
  Mth1 Mth2 Mth3 Mth4
1    1    2    1    3
2   NA    3    2    1
3   NA    2    1    0
4   NA   NA    2    0
5    2    2    0    2

is.na(df)返回指示NA值位置的逻辑矩阵。这(逻辑上)链接到t(apply(!is.na(df), 1, cummax)),表示前一行元素中是否出现非NA值。两个都为TRUE的data.frame元素将替换为0。

答案 1 :(得分:1)

我们可以将applyMARGIN = 1一起使用,找到第一个非NA元素的位置,从中获取序列到最后一个元素,对行进行子集以及replace NA元素为0。

df1[] <- t(apply(df1, 1,  function(x) {
        i1 <- which(!is.na(x))[1]:length(x)
        x[i1] <- replace(x[i1], is.na(x[i1]), 0)
        x}))
df1
#    Mth1 Mth2 Mth3 Mth4
#1    1    2    1    3
#2   NA    3    2    1
#3   NA    2    1    0
#4   NA   NA    2    0
#5    2    2    0    2

另一种选择是基于正则表达式。我们将paste行放在一起,将数字和空格后面的NA元素替换为0,并使用read.table

读取它
read.table(text=gsub("(?<=[0-9])\\s+NA", " 0", 
   do.call(paste, df1), perl = TRUE), header=FALSE, col.names  = names(df1))
#   Mth1 Mth2 Mth3 Mth4
#1    1    2    1    3
#2   NA    3    2    1
#3   NA    2    1    0
#4   NA   NA    2    0
#5    2    2    0    2

数据

df1 <- structure(list(Mth1 = c(1L, NA, NA, NA, 2L), Mth2 = c(2L, 3L, 
2L, NA, 2L), Mth3 = c(1L, 2L, 1L, 2L, NA), Mth4 = c(3L, 1L, NA, 
NA, 2L)), .Names = c("Mth1", "Mth2", "Mth3", "Mth4"), class = "data.frame", 
 row.names = c("1", "2", "3", "4", "5"))