2012-10-12 124 views
6

異常值我有這樣一個數據幀:計算中的R

X

Team 01/01/2012 01/02/2012 01/03/2012 01/01/2012 01/04/2012 SD Mean 
A  100   50   40  NA   30  60 80 

我喜歡在每個單元上的均值和SD來計算異常值進行計算。例如,

abs(x-Mean) > 3*SD 

x$count<-c(1)(如果滿足上述條件,則增加此值)。

我這樣做來檢查我的數據集中的異常。如果我知道列名稱,則計算會更容易,但列數會有所不同。有些細胞可能有NA。

我想從副軌道每個單元的意思是,我想這

x$diff<-sweep(x, 1, x$Mean, FUN='-') 

似乎並不奏效,任何想法?

+1

如果您爲我們提供了一個小樣本數據用'dput(head(x))',那麼我們可以將它剪切並粘貼到我們的瀏覽器中,並測試我們的解決方案。 – nograpes

回答

30

獲取您的IQR(四分位數間距)和下/上四分位使用:

lowerq = quantile(data)[2] 
upperq = quantile(data)[4] 
iqr = upperq - lowerq #Or use IQR(data) 

計算的界限爲溫和的離羣值:

mild.threshold.upper = (iqr * 1.5) + upperq 
mild.threshold.lower = lowerq - (iqr * 1.5) 

的任何數據點外(> mild.threshold。上限或< mild.threshold.lower)這些值是一個溫和的異常值

要檢測極端異常值做同樣的事情,但乘以3代替:

extreme.threshold.upper = (iqr * 3) + upperq 
extreme.threshold.lower = lowerq - (iqr * 3) 

的任何數據點外(> extreme.threshold.upper或< extreme.threshold.lower)這些值是一個極端的異常值

希望這有助於

編輯的:訪問50%,不是75%

+3

應該是'upperq = quantile(data)[4]' – Ben

+0

這將會是一個非常糟糕的算法。例如,當一個相當大的向量可以說80%的數據點在短距離範圍內(例如10-100 ),其餘的20%非常稀疏,那麼這種算法將識別大量的異常值,這可能並不能真實地反映人口中的異常值。 – Bg1850

+2

這裏給出的答案是由於Tukey而衆所周知的方法。見:https://en.wikipedia.org/wiki/Outlier#Tukey.27s_test – stackoverflowuser2010

3

我已經看到你問了一些關於按行操作的問題。你應該避免這種情況。 R遵循以下概念:列表示變量,行表示觀察值。許多功能都根據這個概念進行了優化。如果您需要將寬輸出或轉置輸出轉換爲文件,則可以在寫入文件之前重新排列數據。

我假設你的數據實際上看起來如問題所示,但是你有多行。

df <- read.table(text="Team 01/01/2012 01/02/2012 01/03/2012 01/01/2012 01/04/2012 SD 

Mean 
A  100   50   40  NA   30  60 80 
B  200   40   5   8   NA  NA NA",check.names = FALSE,header=TRUE) 

#needed because one date appears twice 
df <- df[,] 

#reshape the data 
library(reshape2) 
df <- melt(df,id="Team") 
names(df)[2] <- "Date" 

#remove the SD and Mean 
df <- df[!df$Date %in% c("SD","Mean"),] 

#function to detect outliers 
outfun <- function(x) { 
    abs(x-mean(x,na.rm=TRUE)) > 3*sd(x,na.rm=TRUE) 
} 

#test if function works 
outfun(c(200,rnorm(10))) 

#use function over all data 
df3$outlier.all <- outfun(df3$value) 

#apply function for each team 
library(plyr) 
df3 <- ddply(df3,.(Team),transform,outlier.team=outfun(value)) 

結果:

  Date Team value outlier.all outlier.team 
1 01/01/2012 A 100  FALSE  FALSE 
2 01/02/2012 A 50  FALSE  FALSE 
3 01/03/2012 A 40  FALSE  FALSE 
4 01/01/2012.1 A NA   NA   NA 
5 01/04/2012 A 30  FALSE  FALSE 
6 01/01/2012 B 200  FALSE  FALSE 
7 01/02/2012 B 40  FALSE  FALSE 
8 01/03/2012 B  5  FALSE  FALSE 
9 01/01/2012.1 B  8  FALSE  FALSE 
10 01/04/2012 B NA   NA   NA 
+0

嗨@羅蘭。感謝您的答覆。這是一個特例,我有成千上萬的觀察(行),我想找出異常值,然後只繪製它們。我正在將日期轉換爲行,並嘗試檢查每個單元的平均值並計算它達到異常點的次數。然後,我將選擇10或20個項目並繪製它們。基本上,我試圖在我的數據集中捕捉anamolies。 – user1471980

+0

@ user1471980,好吧,我的答案是這樣做的起點。在R中實際上並不難(如果數據是長格式的,我演示瞭如何實現這一點)。根據觀察結果的數量(你寫成千上萬,也可能意味着成千上萬)和數據組,考慮到計算時間,其他方法可能更可取。但是如果我的回答不夠充分,你最好問一個新的問題,提供包括最終目標在內的所有信息。 – Roland

+0

感謝您的意見。根據你的建議,我確實創造了另一個問題,希望我已經提出了點 - http://stackoverflow.com/questions/12888212/detecting-outliers-on-wide-data-frame – user1471980

4

我用@ BY0的回答上面創建一個功能,可自動去除異常值。下面是函數和一些示例代碼:

# generate 10 random numbers and 2 'outlier' numbers 
testData <- c(-42,rnorm(10),42) 

# show the numbers 
testData 

# define a function to remove outliers 
FindOutliers <- function(data) { 
    lowerq = quantile(data)[2] 
    upperq = quantile(data)[4] 
    iqr = upperq - lowerq #Or use IQR(data) 
    # we identify extreme outliers 
    extreme.threshold.upper = (iqr * 3) + upperq 
    extreme.threshold.lower = lowerq - (iqr * 3) 
    result <- which(data > extreme.threshold.upper | data < extreme.threshold.lower) 
} 

# use the function to identify outliers 
temp <- FindOutliers(testData) 

# remove the outliers 
testData <- testData[-temp] 

# show the data with the outliers removed 
testData 
0

下面的公式可用於確定哪些值是異常值:

upper.outlier.calc <- function(x.var, df){with(df, quantile(x.var, 0.75) + (1.5 * (quantile(x.var, 0.75) - quantile(x.var, 0.25))))}

lower.outlier.calc <- function(x.var, df){with(df, quantile(x.var, 0.25) - (1.5 * (quantile(x.var, 0.75) - quantile(x.var, 0.25))))}