Noura
Noura

Reputation: 474

Delete rows with zero value under condition

I have a data frame :

dt <- read.table(text = "
350 16 
366 11 
376  0
380  0
397  0
398 45  
400 19  
402 0
510 0
525 0
537 0
549 0
569 112
578 99")

I want to delete all rows with a zero in the second column except the row before and after a non zero value.

The result will be :

dt1 <- read.table(text = "
350 16 
366 11 
376  0
397  0
398 45  
400 19  
402 0
549 0
569 112
578 99")

Upvotes: 4

Views: 229

Answers (4)

tmfmnk
tmfmnk

Reputation: 40171

Using dplyr:

dt %>%
  filter(lag(V2, 1) != 0 | lead(V2, 1) != 0 | V2 != 0)

    V1  V2
1  350  16
2  366  11
3  376   0
4  397   0
5  398  45
6  400  19
7  402   0
8  549   0
9  569 112
10 578  99

Upvotes: 4

IceCreamToucan
IceCreamToucan

Reputation: 28705

library(data.table)
setDT(dt)

dt[{n0 <- V2 != 0; n0 | shift(n0) | shift(n0, type = 'lead')}]
#or
dt[(n0 <- V2 != 0) | shift(n0) | shift(n0, type = 'lead')] # thanks @Frank

#      V1  V2
#  1: 350  16
#  2: 366  11
#  3: 376   0
#  4: 397   0
#  5: 398  45
#  6: 400  19
#  7: 402   0
#  8: 549   0
#  9: 569 112
# 10: 578  99

Edit:

Now that data.table::shift accepts vectors with some negative and some positive elements you can use the code below instead

dt[Reduce('|', shift(V2 != 0, -1:1))]

Upvotes: 6

M. Papenberg
M. Papenberg

Reputation: 502

This is not dramatically new in comparison to the other responses, but I found the question interesting and so I made my own solution - voilá:

## Function to test if both neighbors of a vector element have the value 0
## Returns a logical vector.
neighbors_zero <- function(x) {
  ## left neighbor is zero?
  rn0 <- c(x[2:length(x)], x[1]) == 0
  ## right neighbor is zero?
  ln0 <- c(x[length(x)], x[1:(length(x)-1)]) == 0
  return(rn0 & ln0)
}

## Test if a value is itsself zero and between other zeros
zero_between_zeros <- dt$V2 == 0 & neighbors_zero(dt$V2)

dt[!zero_between_zeros, ]

Upvotes: 1

Patricio Moracho
Patricio Moracho

Reputation: 717

A simple solution using base R comparing upward and downward displaced vectors

dt[ !(c(dt$V2[-1],0) == 0 & c(0,dt$V2[-length(dt$V2)]) == 0 & dt$V2 == 0), ]

Upvotes: 2

Related Questions