根据df.tr中列的分位数,在df2,3,4中的列中剪切异常值

时间:2014-04-27 03:19:59

标签: r dataframe outliers

我正在尝试用第N个百分位数替换数据框每列中的“异常值”。

n <- 1000
set.seed(1234)
df <- data.frame(a=runif(n), b=rnorm(n), c=rpois(n,1))
df.t1 <- as.data.frame(lapply(df, function(x) { q <- quantile(x,.9,names=F); x[x>q] <- q; x }))

我需要计算的分位数来截断其他数据帧。例如,我在训练数据集上计算这些分位数并应用它;我想在几个测试数据集中使用相同的阈值。这是一种允许的替代方法。

q.df <- sapply(df, function(x) quantile(x,.9,names=F))
df.tmp <- rbind(q.df, df.t1)
df.t2 <- as.data.frame(lapply(df.tmp, function(x) { x[x>x[1]] <- x[1]; x }))
df.t2 <- df.t2[-1,]
rownames(df.t2) <- NULL
identical(df.t1, df.t2)

数据帧非常大,因此我不想使用rbind,然后再删除该行。是否可以使用q.df截断数据帧中的列但不必rbind? THX。

1 个答案:

答案 0 :(得分:3)

所以只需编写一个直接计算分位数的函数,然后直接对每列进行裁剪。您的lapply调用中的<-条件分配是伪造的;您希望ifelse已经为整个列返回一个向量化表达式。 ifelse是你的朋友,用于矢量化。

# Make up some dummy df2 output (it's supposed to have 1000 cols really)
df2 <- data.frame(d=runif(1000), e=rnorm(1000), f=runif(1000))

require(plyr)
print(colwise(summary)(df2))  # show the summary before we clamp...

# Compute quantiles on df1...
df1 <- df
df1.quantiles <- apply(df1, 2, function(x, prob=0.9) { quantile(x, prob, names=F) })

# ...now clamp by sweeping col-index across both quantile vector, and df2 cols
clamp <- function(x, xmax) { ifelse(x<=xmax, x, xmax) }
for (j in 1:ncol(df2)) {
  df2[,j] <- clamp(df2[,j], df1.quantiles[j])  # don't know how to use apply(...,2,)
}

print(colwise(summary)(df2))  # show the summary after we clamp...

参考: [1] "Clip values between a minimum and maximum allowed value in R"