Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I eliminate n-consecutive values from a vector or a list?

Tags:

list

r

vector

Suppose I have:

v <- c(1,2,0,0,0,3,4,4,4,0,0,0,0,5,0)
v
 [1] 1 2 0 0 0 3 4 4 4 0 0 0 0 5 0

I would like to eliminate any consecutive 0's where the number of consecutive 0's is 2+ (2 or more). So the example above would turn into:

1 2 3 4 4 4 5 0

NOTE: I would prefer a base-R solution but other solutions would be interesting

like image 262
Denis Avatar asked Jan 21 '26 10:01

Denis


2 Answers

1) na.locf0 This uses the zoo package but is only one line of code. It makes use of the maxgap argument in na.locf0. Replace each 0 with an NA and everything else with 0. Use na.locf0 with maxgap to fill it in, add it to the original vector, apply na.omit to remove the NAs and use c to remove attributes.

library(zoo)

c(na.omit(na.locf0(ifelse(v == 0, NA, 0), maxgap = 1) + v))
## [1] 1 2 3 4 4 4 5 0

2) rleid This uses rleid from data.table. It is a bit longer than (1) but still reasonably short. It groups the data using rleid and then for each group generates an NA or the original data removing the NAs at the end.

library(data.table)

fun <- function(x) if (x[1] == 0 & length(x) > 1) NA else x
c(na.omit(ave(v, rleid(v), FUN = fun)))
## [1] 1 2 3 4 4 4 5 0
like image 120
G. Grothendieck Avatar answered Jan 24 '26 03:01

G. Grothendieck


An option with rle. We can create a logical condition with rle and extract the values based on that

with(rle(v), {i1 <- !(values == 0 & lengths > 1); rep(values[i1], lengths[i1])})
#[1] 1 2 3 4 4 4 5 0

Note: In the previous version, the OP' output returned only a single value. We just need to replicate with the lengths using the same logic


Or it can be made more compact with rleid

library(data.table)
v[!(ave(v, rleid(v), FUN = length) > 1 & !v)]
#[1] 1 2 3 4 4 4 5 0
like image 22
akrun Avatar answered Jan 24 '26 03:01

akrun



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!