使用聚合结果对R中的数据子集
我正在使用使用聚合结果对R中的数据子集,r,aggregate,outliers,R,Aggregate,Outliers,我正在使用R的stats包中的mad函数来识别异常值。使用aggregate,我可以找到每个因子水平的唯一组合的边界值,如下所示: require(stats) set.seed(492) y <- rnorm(2000) x1 <- sample(letters[1:2], 2000,T) x2 <- sample(letters[1:2], 2000,T) df <- data.frame(y,x1,x2) boundaries <- aggregate(df
R
的stats
包中的mad
函数来识别异常值。使用aggregate
,我可以找到每个因子水平的唯一组合的边界值,如下所示:
require(stats)
set.seed(492)
y <- rnorm(2000)
x1 <- sample(letters[1:2], 2000,T)
x2 <- sample(letters[1:2], 2000,T)
df <- data.frame(y,x1,x2)
boundaries <- aggregate(df$y, list(df$x1, df$x2), function(x) cbind(median(x)
+ (3*mad(x)), median(x) - (3*mad(x))))
x.1
是上限,x.2
是下限。我想对df进行子集df
,以便去除每个因子水平组合的异常值-例如,在a.a中,我不希望任何值高于2.88或低于-2.80,但对于a.b,我希望上限值为3.14,下限值为-2.96
到目前为止,我已尝试使用by
,但它返回长度为0行的数据帧:
by(df$y, list(df$x1, df$x2), function(x) df[which(df$y>(median(x) + (3*mad(x))) & df$y<(median(x) - (3*mad(x)))),])
by(df$y,list(df$x1,df$x2),function(x)df[which(df$y>(中位数(x)+(3*mad(x))&df$y我想你可以使用merge
然后使用一些标准的子集。在下面,我修改了你的aggregate
语句,得到更好的名称,使merge
更简单。我还使用了do.call(data.frame,…)
将矩阵列展平为聚合的data.frame中的列
boundaries <- aggregate(y ~ x1 + x2, df, function(x)
cbind(median(x) + (3*mad(x)), median(x) - (3*mad(x))))
boundaries <- do.call(data.frame, boundaries)
out <- merge(df, boundaries)
head(out)
# x1 x2 y y.1 y.2
# 1 a a -0.4003471 2.87556 -2.809068
# 2 a a -0.5652717 2.87556 -2.809068
# 3 a a 0.1185306 2.87556 -2.809068
# 4 a a 1.2634333 2.87556 -2.809068
# 5 a a 0.3585731 2.87556 -2.809068
# 6 a a -0.1436202 2.87556 -2.809068
out2 <- out[with(out, y.2 < y & y < y.1), c("y", "x1", "x2")]
head(out2)
# y x1 x2
# 1 -0.4003471 a a
# 2 -0.5652717 a a
# 3 0.1185306 a a
# 4 1.2634333 a a
# 5 0.3585731 a a
# 6 -0.1436202 a a
dim(out2)
# [1] 1993 3
bounders我想你可以使用merge
然后使用一些标准的子集。在下面,我修改了你的aggregate
语句,使merge
更简单。我还使用了do.call(data.frame,…)
将矩阵列展平为聚合的data.frame中的列
boundaries <- aggregate(y ~ x1 + x2, df, function(x)
cbind(median(x) + (3*mad(x)), median(x) - (3*mad(x))))
boundaries <- do.call(data.frame, boundaries)
out <- merge(df, boundaries)
head(out)
# x1 x2 y y.1 y.2
# 1 a a -0.4003471 2.87556 -2.809068
# 2 a a -0.5652717 2.87556 -2.809068
# 3 a a 0.1185306 2.87556 -2.809068
# 4 a a 1.2634333 2.87556 -2.809068
# 5 a a 0.3585731 2.87556 -2.809068
# 6 a a -0.1436202 2.87556 -2.809068
out2 <- out[with(out, y.2 < y & y < y.1), c("y", "x1", "x2")]
head(out2)
# y x1 x2
# 1 -0.4003471 a a
# 2 -0.5652717 a a
# 3 0.1185306 a a
# 4 1.2634333 a a
# 5 0.3585731 a a
# 6 -0.1436202 a a
dim(out2)
# [1] 1993 3
bounders这里是一个使用plyr
的解决方案。它使用split-apply-combine范式。我们首先使用列x1
和x2
将数据框拆分为若干部分。对于每个部分d
(这是一个数据框)我们计算出的外部限制,我们将考虑<代码> y>代码>离群值,然后使用逻辑索引只返回不属于异常值的<代码> d>代码>行。
library(plyr)
df2 = ddply(df, .(x1, x2), function(d){
limits = median(d$y) + 3*c(-1, 1)*mad(d$y)
d[(d$y - limits[1])*(limits[2] - d$y) > 0,]
})
这里是一个使用plyr
的解决方案。它使用拆分应用组合范例。我们首先使用列x1
和x2
将数据帧拆分为多个片段。对于每个片段d
(这是一个数据帧)我们计算出的外部限制,我们将考虑<代码> y>代码>离群值,然后使用逻辑索引只返回不属于异常值的<代码> d>代码>行。
library(plyr)
df2 = ddply(df, .(x1, x2), function(d){
limits = median(d$y) + 3*c(-1, 1)*mad(d$y)
d[(d$y - limits[1])*(limits[2] - d$y) > 0,]
})
此函数过滤值以满足您的条件,其结构可避免不必要的中位数和mad重新计算
filt <- function (x) {
b <- median(x) + mad(x) * c(-3, 3)
x[x > b[1] & x < b[2]]
}
filt此函数过滤值以满足您的条件,其结构可避免不必要的中位数和mad重新计算
filt <- function (x) {
b <- median(x) + mad(x) * c(-3, 3)
x[x > b[1] & x < b[2]]
}
filt“x.2”是否也代表下限?是的,对不起!我会在问题中澄清。“x.2”是否也代表下限?是的,对不起!我会在问题中澄清。R
报告“[.default”(xj,I)中的错误:当我尝试最初创建边界时,下标类型“closure”无效。
知道可能发生了什么吗?@luser,是您的实际数据。frame
称为“df”?您发布的这个示例数据集是否存在相同的问题?我的实际数据。frame
未调用df
或任何其他系统保留名称。当我清除我的工作区并复制粘贴我放在这里的代码时,我也有相同的问题。@luser,您使用的是什么版本的R?sessionInfo()
reports 3.0.2R
reportsError in'[.default'(xj,i):当我尝试最初创建边界时,无效的下标类型“closure”
。知道会发生什么吗?@luser,是您实际的数据。frame
称为“df”?您发布的这个示例数据集是否存在相同的问题?我的实际数据。frame
未调用df
或任何其他系统保留名称。当我清除我的工作区并复制粘贴我放在这里的代码时,我也有相同的问题。@luser,您使用的是什么版本的R?sessionInfo()
reports 3.0.2我最初尝试使用ddply
,但没有结果。感谢您的解释,我现在对如何使用plyr
有了一点了解。我最初尝试使用ddply
,但没有结果。感谢您的解释,我现在对如何使用plyr
有了一点了解。