ArTu
ArTu

Reputation: 483

locf and nocb function

I would like to create a function using this as base:

locf <- function(x) {
  a <- x[1]
  for (i in 2:length(x)) {
    if (is.na(x[i])) x[i] <- a
    else a <- x[i]
  }
  return(x)
}

This function is just LOCF, I would like to create a function that is LOCF for all the missing data and NOCB for the first missing observation.

My data:

data<-c(NA, 24.107, NA, 26.912, NA, 30.193, NA, 19.003, NA, NA, 28.578, NA, NA, 33.484, 32.952, 13.574, NA, NA, 38.782, NA, NA, NA, 28.804, NA, 27.042, NA, NA, NA, NA, 21.344, NA, 21.507, NA, NA, NA, 16.508, NA, NA, 14.015, 11.738, 15.055)

What i want to obtain:

locf<-c(24.107, 24.107, 24.107, 26.912, 26.912, 30.193, 30.193, 19.003, 19.003, 19.003, 28.578, 28.578, 28.578, 33.484, 32.952, 13.574, 13.574, 13.574, 38.782, 38.782, 38.782, 38.782, 28.804, 28.804, 27.042, 27.042, 27.042, 27.042, 27.042, 21.344, 21.344, 21.507, 21.507, 21.507, 21.507, 16.508, 16.508, 16.508, 14.015, 11.738, 15.055)

Thank you in advance.

Upvotes: 0

Views: 787

Answers (3)

Steffen Moritz
Steffen Moritz

Reputation: 7730

Exactly this function exists in the imputeTS package:

library(imputeTS)
imputeTS::na.locf(x, option = "locf", na.remaining = "rev")

With the na.remaining parameter you can choose what shall be done with the remaining trailing NAs. You can for choose between "rev" (reverse), "mean" or "keep". Choosing "rev" does nocb for all NAs at the beginning that could not be filled by locf. If you choose to do option = "nocb" instead of "locf" in the first place it would of course then fill the trailing NAs with "locf".

Upvotes: 0

IRTFM
IRTFM

Reputation: 263332

This sets the first na to be the next value and then resets subsequent na’s by their locf values.

#library(zoo)
Nocb1.locf <- function (x){ wh1st <- which(is.na(x))[1]; 
   x[wh1st] <- x[wh1st + 1]
   x <- zoo::na.locf(x) }

Upvotes: 1

ozanstats
ozanstats

Reputation: 2856

If you refer to the first element of the list by "first missing observation", the following would work:

my_function <- function(my_list) {
  for(i in 1:length(my_list)) {
    if(is.na(my_list[i])) {
      if(i == 1) {
        my_list[i] <- my_list[i + 1]
      } else {
        print(i)
        my_list[i] <- my_list[i - 1]
      }
    }
  }
  return(my_list)
}

If you want to treat the first NA observation of the list differently regardless of its location (i.e. it may be third element of the list overall), you can tweak the function:

my_function <- function(my_list) {
  first <- 0
  for(i in 1:length(my_list)) {
    if(is.na(my_list[i])) {
      if(first == 0) {
        my_list[i] <- my_list[i + 1]
        first <- 1
      } else {
        print(i)
        my_list[i] <- my_list[i - 1]
      }
    }
  }
  return(my_list)
}

Upvotes: 1

Related Questions