用R中的最后已知值替换异常值

时间:2018-03-26 14:05:19

标签: r outliers

示例数据: 2 4 6 10 99 150 14 15 45

问题的先验知识,我知道35以上的任何东西都是异常值,但由于数据取决于时间,我想用35以下的最后已知数字替换35以上的所有值。数据集包含数百万行,所以我需要自动执行此操作而不是逐个替换。

所需结果:2 4 6 10 10 10 14 15 15

2 个答案:

答案 0 :(得分:2)

s

答案 1 :(得分:0)

对于那些不希望 zoo 包依赖的用户,这是一个简单的版本,使用了来自base的运行级别编码。这个想法很简单,我们只用rle()并将索引中的NA替换为左边的任何值(即前一个值),然后跳过任何前NA,因为左边没有价值。然后,我们使用inverse.rle()返回到全长向量。对于逆向运算(,我们只是在向量前后进行逆向运算。我没有进行基准测试,但是由于所有运算都是向量化的,因此应该相当快。

rle()由于某种原因未将NA分组。文档指出:“缺少的值也被认为与先前的值不相等,即使它也丢失了。”因此,为什么我将NA重新编码为一个临时字符串值,并且必须将向量转换回正确的类。并不完美,但在大多数情况下都可以使用。

#' Last observation carried forward
#'
#' @param x A vector
#' @param reverse Whether to do it in reverse
#'
#' @return A vector
#' @export
#'
#' @examples
#' c(NA, 1, NA, 2, NA) %>% locf()
#' c(NA, 1, NA, 2, NA) %>% locf(reverse = T)
locf = function(x, reverse = F) {
  #reverse?
  if (reverse) x = rev(x)

  #recode NA
  #these are kept distinct by rle() by default for same reason ???
  x_class = class(x)
  x[is.na(x)] = "___tmp"

  #run level encoding
  x_rle = rle(x)

  #swap values for NAs
  which_na = which(x_rle$values == "___tmp")

  #skip 1st
  which_na = setdiff(which_na, 1)

  #replace values
  x_rle$values[which_na] = x_rle$values[which_na - 1]

  #back to normal
  y = inverse.rle(x_rle)

  #NA recode
  y[y == "___tmp"] = NA

  #fix type/class
  if (x_class[1] == "logical") y = as.logical(y)
  if (x_class[1] == "integer") y = as.integer(y)
  if (x_class[1] == "numeric") y = as.double(y)
  if (x_class[1] == "factor") y = factor(y, levels = levels(x))
  if (x_class[1] == "ordered") y = ordered(y, levels = levels(x))

  #reverse?
  if (reverse) y = rev(y)

  y
}

测试:

> c(NA, 1, NA, 2, NA) %>% rle()
Run Length Encoding
  lengths: int [1:5] 1 1 1 1 1
  values : num [1:5] NA 1 NA 2 NA
> c(NA, 1, NA, 2, NA) %>% rle() %>% str()
List of 2
 $ lengths: int [1:5] 1 1 1 1 1
 $ values : num [1:5] NA 1 NA 2 NA
 - attr(*, "class")= chr "rle"
> #swap the values for one to left
> #reverse rle
> c(NA, 1, NA, 2, NA) %>% locf()
[1] NA  1  1  2  2
> c(NA, 1, NA, 2, NA) %>% locf(reverse = T)
[1]  1  1  2  2 NA
> c(NA, 1, NA, 2, NA, NA, NA) %>% locf()
[1] NA  1  1  2  2  2  2