2014-03-25 52 views
1

我使用Rstats包中的mad函數來識別異常值。使用aggregate,我能找到的邊界值因子含量的,像這樣每一個獨特的組合:在R中使用聚合子集數據的結果

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)))) 

其中給出:

+---------------------------------------+ 
| Group.1 Group.2  x.1  x.2 | 
+---------------------------------------+ 
| 1  a  a 2.875560 -2.809068 | 
| 2  b  a 2.867109 -2.843691 | 
| 3  a  b 3.137889 -2.960135 | 
| 4  b  b 3.091169 -3.134296 | 
+---------------------------------------+ 

x.1是上限和x.2是下限。我想要子集df,以便對每個因子級別的組合刪除異常值 - 例如,在aa中,我不希望任何高於2.88或-2.80的值,但對於ab,我希望上限值爲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)))),]) 

任何指導是非常讚賞。

+0

「x.2」是否也代表下限? – A5C1D2H2I1M1N2O1R2T1

+0

是的,對不起!我會在問題中澄清。 – luser

回答

1

這是使用plyr的解決方案。它使用拆分應用組合範例。我們首先使用列x1x2將數據幀拆分成小塊。對於每個片段d(它是一個數據幀),我們計算出其中我們將認爲是異常值y的界限,然後使用邏輯索引來僅返回那些非異常值的那些行d。最後,ddply負責將所有子集化的片段組合成單個數據幀。

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,] 
}) 
+0

我最初嘗試使用'ddply',但沒有得到任何好處。感謝您的解釋,我明白如何使用'plyr'現在好一點。 – luser

3

我想你可以使用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 
+0

'R'報告'[.default'(xj,i)中的錯誤:當我嘗試初始創建'邊界'時無效的下標類型'closure'。任何想法可能會發生什麼? – luser

+0

@luser,你實際的'data.frame'叫做「df」嗎?您是否與您發佈的此示例數據集有同樣的問題? – A5C1D2H2I1M1N2O1R2T1

+0

我的實際'data.frame'不叫'df'或任何其他系統保留名稱。當我清除工作空間並複製粘貼我放在這裏的代碼時,我遇到了同樣的問題。 – luser

0

該功能篩選值,以滿足你的條件,結構化,以避免位的不必要的重新計算和狂

filt <- function (x) { 
    b <- median(x) + mad(x) * c(-3, 3) 
    x[x > b[1] & x < b[2]] 
} 

骨料自己的原始數據幀,其結果列「Y」是一個列表滿足過濾準則-of-矢量

df1 <- aggregate(y ~ x1 + x2, df, filt, simplify=FALSE) 

指示器變量然後複製,並且該列表的向量未上市,以獲得最終的represe到達ntation

len <- sapply(df1$y, length) 
result <- data.frame(x1=rep(df1$x1, len), x2=rep(df1$x2, len), 
        y=unlist(df1$y, use.names=FALSE))