簡體   English   中英

使用聚合結果對R中的數據進行子集

[英]Using results of aggregate to subset data in R

我正在使用Rstats包中的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))))

這使:

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

任何指導是非常感謝。

我想您可以使用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

這是使用plyr的解決方案。 它使用split-apply-combine范例。 我們首先使用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,]
})

此函數過濾值以滿足您的條件,其結構避免不必要地重新計算中值和瘋狂

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

匯總原始數據幀,結果列“ y”是滿足過濾條件的向量列表

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

然后復制指標變量,並且不列出向量列表,以得出最終表示形式

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM