7

I need to delete leading and trailing missing values (NA) from a vector. NAs between numbers should be kept. Note that my next step is index another vector without NA and keep only values with the same position as in first vector. Here is the example:

a <- c(NA, NA, NA, NA, NA, 5,2,3,1,2,1,5,2, NA, NA, 2,3,2,NA,NA,NA)
b <- sample(1:21)

My desired output is:

a1 <- c(5,2,3,1,2,1,5,2,NA,NA,2,3,2)
# leading and trailing NAs removed

b1 <- b[6:18]
# subset with the indices kept in "a" above.

I thing I can do this with come conditional loop but I want to vectorize it. Thx for help!

Henrik
  • 65,555
  • 14
  • 143
  • 159
Bobesh
  • 1,157
  • 2
  • 15
  • 30
  • 1
    [this to count NAs](http://stackoverflow.com/questions/22752617/how-to-simplify-a-leading-na-count-function-and-generalize-it-to-work-on-matrix), and [this to trim](http://stackoverflow.com/questions/36639599/remove-leading-nas-to-align-data) – Sotos Mar 13 '17 at 08:22

3 Answers3

6

Look for the first and the last non-NA value and keep that part of the vector:

a1 <- a[min(which(!is.na(a))):max(which(!is.na(a)))]

> a1
[1]  5  2  3  1  2  1  5  2 NA NA  2  3  2
ottlngr
  • 1,137
  • 7
  • 13
  • This solution is clear, but how will the OP do his next step after that? Maybe you should edit to something like: `p <- which(!is.na(a)) ; a1 <- a[p[1]:p[length(p)]] ; b1 <- b[p[1]:p[length(p)]]`? – Scarabee Mar 13 '17 at 10:04
5
keep <- !cumprod(is.na(a)) & rev(!cumprod(is.na(rev(a))))
a[keep]
#[1]  5  2  3  1  2  1  5  2 NA NA  2  3  2
b[Keep]

is.na returns TRUE for NA values. The cumprod function coerces the logical values to integers and returns 1 for the leading NAs and 0 for all other values. ! (negation) coerces the integer values to logical values again. We then use rev for the trailing NAs.

Roland
  • 127,288
  • 10
  • 191
  • 288
5

Using zoo package:

library(zoo)

na.trim(a)

Description

Generic function for removing leading and trailing NAs.

zx8754
  • 52,746
  • 12
  • 114
  • 209