user2904120
user2904120

Reputation: 416

Remove outliers based on a preceding value

How to remove outliers using a criterion that a value cannot be more than 2-fold higher then its preceding one.

Here is my try:

x<-c(1,2,6,4,10,20,50,10,2,1)

remove_outliers <- function(x, na.rm = TRUE, ...) {
  for(i in 1:length(x))
  x < (x[i-1] + 2*x)
  x
}

remove_outliers(y)

expected outcome: 1,2,4,10,20,2,1

Thanks!

Upvotes: 0

Views: 64

Answers (2)

Pierre Lapointe
Pierre Lapointe

Reputation: 16277

I think the first 10 should be removed in your data because 10>2*4. Here's a way to do what you want without loops. I'm using the dplyr version of lag.

library(dplyr)
x<-c(1,2,6,4,10,20,50,10,2,1)
x[c(TRUE,na.omit(x<=dplyr::lag(x)*2))]
[1]  1  2  4 20 10  2  1

EDIT

To use this with a data.frame:

df <- data.frame(id=1:10, x=c(1,2,6,4,10,20,50,10,2,1))
df[c(TRUE,na.omit(df$x<=dplyr::lag(df$x,1)*2)),]

   id  x
1   1  1
2   2  2
4   4  4
6   6 20
8   8 10
9   9  2
10 10  1

Upvotes: 2

amonk
amonk

Reputation: 1795

A simple sapply:

bool<-sapply(seq_along(1:length(x)),function(i) {ifelse(x[i]<2*x[i-1],FALSE,TRUE)})

 bool
[[1]]
logical(0)

[[2]]
[1] TRUE

[[3]]
[1] TRUE

[[4]]
[1] FALSE

[[5]]
[1] TRUE

[[6]]
[1] TRUE

[[7]]
[1] TRUE

[[8]]
[1] FALSE

[[9]]
[1] FALSE

[[10]]
[1] FALSE

resulting in:

x[unlist(bool)]
[1]  1  2  4 10 20  1

Upvotes: 0

Related Questions