Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace 0s with next non-zero value in column R

Tags:

replace

r

fill

Someone else gave me a data set that looks kind of like this.

input = c(0,0,0,0,1,0,0,0,0,0,0,2,0,1,0,0,2)

What I need to do is fill the 0's with the next non-zero number (it will always be a 1 or 2). Also, this next non-zero number needs to be filled be the next one (The last value can be anything because I am going to set it to NA anyway).

So the function should return this

> output =c(1,1,1,1,2,2,2,2,2,2,2,1,1,2,2,2,NA)
> cbind(input,output)
      input output
 [1,]     0      1
 [2,]     0      1
 [3,]     0      1
 [4,]     0      1
 [5,]     1      2
 [6,]     0      2
 [7,]     0      2
 [8,]     0      2
 [9,]     0      2
[10,]     0      2
[11,]     0      2
[12,]     2      1
[13,]     0      1
[14,]     1      2
[15,]     0      2
[16,]     0      2
[17,]     2     NA

Thanks!

-- Edited Part --

The output only needs to be an array/vector (or whatever the proper term in R is). The example I bound the 2 together to demonstrate the offset by 1 as well as the filling. Thanks for the great answers guys

like image 468
qwertylpc Avatar asked Nov 22 '25 10:11

qwertylpc


2 Answers

output=input[!!input][cumsum(!!input)+1]
#[1]  1  1  1  1  2  2  2  2  2  2  2  1  1  2  2  2 NA

We take advantage of how R coerces numbers to logicals. as.logical(0:2) will return FALSE TRUE TRUE. Zeros become FALSE and the other numbers are considered TRUE. Putting the negation exclamation point in front of input coerces it to logical. I could have written as.logical(input), it's just a trick to save a few keystrokes. So we use that logical index to subset the non-zero values with input[!!input]. The cumulative sum of a logical index cumsum(!!input)+1 creates a quick way to index on the change points when you add one to it. It helps to run each part separately.

like image 106
Pierre L Avatar answered Nov 25 '25 05:11

Pierre L


Set the 0 values to NA and use na.locf:

input[input==0] <- NA
na.locf(input, fromLast=TRUE)
## [1] 1 1 1 1 1 2 2 2 2 2 2 2 1 1 2 2 2

From ?na.locf:

Generic function for replacing each NA with the most recent non-NA prior to it.

like image 22
Matthew Lundberg Avatar answered Nov 25 '25 04:11

Matthew Lundberg