我正在尝试用第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。
答案 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"