Cách xóa các giá trị ngoại lai khỏi tập dữ liệu


98

Tôi có một số dữ liệu đa biến về sắc đẹp so với tuổi. Độ tuổi dao động từ 20-40 trong khoảng thời gian là 2 (20, 22, 24 .... 40) và đối với mỗi bản ghi dữ liệu, chúng được đánh giá độ tuổi và độ đẹp từ 1-5. Khi tôi thực hiện các sơ đồ hộp của dữ liệu này (độ tuổi trên trục X, xếp hạng vẻ đẹp trên trục Y), có một số ngoại lệ được vẽ bên ngoài râu của mỗi hộp.

Tôi muốn loại bỏ những giá trị ngoại lệ này khỏi chính khung dữ liệu, nhưng tôi không chắc cách R tính toán những giá trị ngoại lệ cho các ô hộp của nó. Dưới đây là ví dụ về dữ liệu của tôi có thể trông như thế nào. nhập mô tả hình ảnh ở đây


2
Các boxplotchức năng trả về giá trị ngoại biên (trong số liệu thống kê khác) vô hình. Hãy thử foo <- boxplot(...); foovà đọc ?boxplotđể hiểu đầu ra.
Joshua Ulrich

Bạn nên chỉnh sửa câu hỏi của mình theo nhận xét mà bạn đã đưa ra về câu trả lời của @ Prasad!
aL3xa

@ aL3xa: nó nằm ở câu đầu tiên của đoạn thứ hai.
Joshua Ulrich

24

Bạn có thể gửi một liên kết đến dữ liệu?
wordsforthewise

Câu trả lời:


119

OK, bạn nên áp dụng một cái gì đó như thế này cho tập dữ liệu của mình. Đừng thay thế và lưu, nếu không bạn sẽ phá hủy dữ liệu của mình! Và, btw, bạn nên (hầu như) không bao giờ loại bỏ các ngoại lệ khỏi dữ liệu của mình:

remove_outliers <- function(x, na.rm = TRUE, ...) {
  qnt <- quantile(x, probs=c(.25, .75), na.rm = na.rm, ...)
  H <- 1.5 * IQR(x, na.rm = na.rm)
  y <- x
  y[x < (qnt[1] - H)] <- NA
  y[x > (qnt[2] + H)] <- NA
  y
}

Để xem nó hoạt động:

set.seed(1)
x <- rnorm(100)
x <- c(-10, x, 10)
y <- remove_outliers(x)
## png()
par(mfrow = c(1, 2))
boxplot(x)
boxplot(y)
## dev.off()

Và một lần nữa, bạn không bao giờ nên làm điều này một mình, các ngoại lệ chỉ có nghĩa là như vậy! =)

CHỈNH SỬA: Tôi đã thêm na.rm = TRUElàm mặc định.

EDIT2: Đã xóa quantilechức năng, thêm ghi chỉ số, do đó làm cho chức năng nhanh hơn! =)

nhập mô tả hình ảnh ở đây


Cảm ơn đã giúp đỡ! Tôi sẽ nghĩ nếu R có khả năng xuất ra các giá trị ngoại lệ trong ô boxplot, tôi không cần phải thực hiện các phép tính trung gian này. Đối với việc xóa các ngoại lệ, đây chỉ là một nhiệm vụ.
Dan Q

3
OK, tôi đang thiếu một cái gì đó ở đây. Bạn muốn loại bỏ các giá trị ngoại lai khỏi dữ liệu, vì vậy bạn có thể lập biểu đồ cho chúng boxplot. Điều đó có thể quản lý được và bạn nên đánh dấu câu trả lời của @ Prasad sau đó, vì đã trả lời câu hỏi của bạn. Nếu bạn muốn loại trừ các ngoại lệ bằng cách sử dụng "quy tắc ngoại lệ" q +/- (1.5 * H), do đó hãy chạy một số phân tích, sau đó sử dụng chức năng này. BTW, tôi đã làm điều này từ đầu, w / o Googling, vì vậy có một cơ hội mà tôi đã reenvented bánh xe với chức năng này của tôi ...
aL3xa

10
Bạn không nên đặt câu hỏi về bài tập trên stackoverflow!
hadley

7
Điều đó có nghĩa là chúng ta cũng không nên trả lời nó? =)
aL3xa

5
"ngoại lệ chỉ có nghĩa là"? Không cần thiết. Chúng có thể xuất phát từ sai số đo lường và phải được xem xét kỹ lưỡng. Khi giá trị ngoại lệ quá lớn, nó có thể có ý nghĩa gì đó, hoặc không quá nhiều. Đó là lý do tại sao (ít nhất là trong sinh học) giá trị trung bình thường nói về một dân số nhiều hơn mức trung bình.
Rodrigo

132

Không ai đã đăng câu trả lời đơn giản nhất:

x[!x %in% boxplot.stats(x)$out]

Xem thêm tại đây: http://www.r-stosystem.com/2011/01/how-to-label-all-the-outaries-in-a-boxplot/


4
Thực sự thanh lịch. Cảm ơn. Nhưng cần phải cẩn thận nếu phân phối có nhiều hơn một chế độ và các trường hợp ngoại lệ thực sự chỉ là ít và rải rác.
KarthikS

Sẽ thật tuyệt nếu bạn có thể lấy chỉ mục của chúng trong một tập dữ liệu. Cách bạn thực hiện sẽ lọc dựa trên giá trị dữ liệu. Nếu ô hộp cũng đang thực hiện phân nhóm, không nhất thiết giá trị dữ liệu giống nhau sẽ ngoại lệ trong mỗi nhóm
adam

2
Điều quan trọng cần đề cập là nó không thay đổi tập dữ liệu. Đây chỉ là một phương pháp lọc. Vì vậy, nếu bạn có ý định sử dụng tập dữ liệu mà không có ngoại lệ, hãy gán nó cho một biến. ví dụresult = x[!x %in% boxplot.stats(x)$out]
Victor Augusto

Chỉ có một dòng mã không nhất thiết có nghĩa là nó đơn giản! Không phải lúc nào cũng dễ hiểu mã một dòng, đặc biệt cho người mới bắt đầu và không có bình luận.
PeyM87,

29

Sử dụng outline = FALSEnhư một tùy chọn khi bạn thực hiện boxplot (đọc phần trợ giúp!).

> m <- c(rnorm(10),5,10)
> bp <- boxplot(m, outline = FALSE)

nhập mô tả hình ảnh ở đây


4
thực sự, điều này sẽ loại bỏ các ngoại lệ khỏi chính boxplot, nhưng tôi muốn loại bỏ các ngoại lệ khỏi khung dữ liệu.
Dan Q

2
Tôi hiểu rồi, như @Joshua đã nói bạn cần xem dữ liệu được trả về bởi hàm boxplot (cụ thể là các mục outgrouptrong danh sách).
Prasad Chalasani

16

Hàm boxplot trả về các giá trị được sử dụng để vẽ biểu đồ (sau đó thực sự được thực hiện bởi bxp ():

bstats <- boxplot(count ~ spray, data = InsectSprays, col = "lightgray") 
#need to "waste" this plot
bstats$out <- NULL
bstats$group <- NULL
bxp(bstats)  # this will plot without any outlier points

Tôi đã cố tình không trả lời câu hỏi cụ thể vì tôi coi đó là sơ suất thống kê để loại bỏ các "ngoại lệ". Tôi coi việc không vẽ chúng trong một ô vuông là một thực tiễn có thể chấp nhận được, nhưng việc loại bỏ chúng chỉ vì chúng vượt quá một số độ lệch chuẩn hoặc một số độ rộng giữa các phần tư là một sự xáo trộn có hệ thống và không khoa học đối với hồ sơ quan sát.


4
Chà, bỏ qua câu hỏi mà không biết tại sao câu hỏi được đặt ra cũng không phải là một cách làm hay. Có, việc loại bỏ 'ngoại lệ' khỏi dữ liệu là không tốt nhưng đôi khi bạn cần dữ liệu không có ngoại lệ cho các nhiệm vụ cụ thể. Trong một bài tập thống kê mà tôi đã thực hiện gần đây, chúng tôi phải hình dung một tập hợp không có ngoại lệ của nó để xác định mô hình hồi quy tốt nhất để sử dụng cho dữ liệu. Vì vậy, có!
Alex Essilfie

4
Tôi không xem lời khuyên mà bạn có thể nhận được về vấn đề này để "xác định mô hình hồi quy tốt nhất" là đặc biệt thuyết phục. Thay vào đó, nếu bạn cần loại bỏ các ngoại lệ cho mục đích mơ hồ đó, thì tôi nghĩ rằng nó phản ánh không tốt về những người đã tư vấn nó hơn là bằng chứng về sự không hợp lệ của vị trí của tôi.
IRTFM

Tôi đoán nó hợp pháp khi bạn biết bạn đang loại bỏ "tiếng ồn". đặc biệt là trong dữ liệu sinh lý.
roscoe1895

Đúng. Nếu bạn có lý do chính đáng để tin rằng một quy trình riêng biệt tạo ra tín hiệu, thì đó là lý do chính đáng để xóa khỏi dữ liệu.
IRTFM

9

Tôi đã tìm kiếm các gói liên quan đến việc loại bỏ các ngoại lệ và tìm thấy gói này (đáng ngạc nhiên là "các ngoại lệ"!): Https://cran.r-project.org/web/packages/outlier/outaries.pdf
nếu bạn đã xem qua nó. xem các cách khác nhau để loại bỏ các giá trị ngoại lệ và trong số đó, tôi thấy rm.outliercách thuận tiện nhất để sử dụng và như nó đã nói trong liên kết ở trên: "Nếu các giá trị ngoại lệ được phát hiện và xác nhận bằng các thử nghiệm thống kê, chức năng này có thể loại bỏ nó hoặc thay thế bằng giá trị trung bình hoặc giá trị trung bình của mẫu" và đây cũng là phần sử dụng từ cùng một nguồn:
" Cách sử dụng

rm.outlier(x, fill = FALSE, median = FALSE, opposite = FALSE)

Đối số
x một tập dữ liệu, thường là một vectơ. Nếu đối số là khung dữ liệu, thì giá trị ngoại lệ bị sapply loại bỏ khỏi mỗi cột. Hành vi tương tự được áp dụng bằng cách áp dụng khi ma trận được đưa ra.
điền Nếu được đặt thành TRUE, giá trị trung bình hoặc giá trị trung bình được đặt thay vì đặt giá trị ngoại lệ. Nếu không, (các) ngoại lệ chỉ bị / bị loại bỏ.
Trung bình Nếu được đặt thành TRUE, trung vị được sử dụng thay vì trung bình trong thay thế ngoại lệ. ngược lại nếu được đặt thành TRUE, cho giá trị ngược lại (nếu giá trị lớn nhất có chênh lệch lớn nhất so với giá trị trung bình, nó cho giá trị nhỏ nhất và ngược lại) "


Điều này có vẻ tuyệt vời, nhưng nếu bạn có cột chuỗi thời gian trong khung dữ liệu của mình, nó sẽ thay đổi chuỗi thời gian.
PeyM87

7
x<-quantile(retentiondata$sum_dec_incr,c(0.01,0.99))
data_clean <- data[data$attribute >=x[1] & data$attribute<=x[2],]

Tôi thấy điều này rất dễ dàng để loại bỏ các ngoại lệ. Trong ví dụ trên, tôi chỉ trích xuất 2 phân vị đến 98 phân vị của các giá trị thuộc tính.


5

Sẽ không:

z <- df[df$x > quantile(df$x, .25) - 1.5*IQR(df$x) & 
        df$x < quantile(df$x, .75) + 1.5*IQR(df$x), ] #rows

hoàn thành nhiệm vụ này khá dễ dàng?


4

Thêm vào đề xuất của @sefarkas và sử dụng quantile làm giới hạn, người ta có thể khám phá tùy chọn sau:

newdata <- subset(mydata,!(mydata$var > quantile(mydata$var, probs=c(.01, .99))[2] | mydata$var < quantile(mydata$var, probs=c(.01, .99))[1]) ) 

Điều này sẽ loại bỏ các điểm vượt quá lượng tử thứ 99. Cần phải cẩn thận như những gì aL3Xa đã nói về việc giữ cho các ngoại lệ. Nó chỉ nên được xóa để có được một cái nhìn thận trọng thay thế về dữ liệu.


là nó 0.91hay 0.99? như trong mydata$var < quantile(mydata$var, probs=c(.01, .91))[1])hoặcmydata$var < quantile(mydata$var, probs=c(.01, .99))[1])
Komal Rathi

Nếu bạn có lý do cụ thể để sử dụng phân vị thứ 91 thay vì phân vị thứ 99, bạn có thể sử dụng nó. Nó chỉ là một heuristic
KarthikS

1

1 cách để làm điều đó là

my.NEW.data.frame <- my.data.frame[-boxplot.stats(my.data.frame$my.column)$out, ]

hoặc là

my.high.value <- which(my.data.frame$age > 200 | my.data.frame$age < 0) 
my.NEW.data.frame <- my.data.frame[-my.high.value, ]

0

Các giá trị ngoại lai khá giống với các đỉnh, vì vậy một bộ dò đỉnh có thể hữu ích để xác định các giá trị ngoại lệ. Phương pháp được mô tả ở đây có hiệu suất khá tốt bằng cách sử dụng điểm số z. Phần hoạt ảnh ở cuối trang minh họa phương pháp báo hiệu về các giá trị ngoại lệ hoặc đỉnh.

Các đỉnh không phải lúc nào cũng giống như giá trị ngoại lai, nhưng chúng thường giống nhau.

Một ví dụ được hiển thị ở đây: Tập dữ liệu này được đọc từ một cảm biến thông qua giao tiếp nối tiếp. Đôi khi lỗi giao tiếp nối tiếp, lỗi cảm biến hoặc cả hai dẫn đến các điểm dữ liệu bị sai sót rõ ràng, lặp lại. Không có giá trị thống kê ở điểm này. Chúng được cho là không ngoại lệ, chúng là lỗi. Bộ dò đỉnh điểm z có thể phát tín hiệu trên các điểm dữ liệu giả và tạo ra một tập dữ liệu kết quả sạch:nhập mô tả hình ảnh ở đây


-1

Thử cái này. Nạp biến của bạn trong hàm và lưu o / p trong biến chứa các giá trị ngoại lệ đã bị loại bỏ

outliers<-function(variable){
    iqr<-IQR(variable)
    q1<-as.numeric(quantile(variable,0.25))
    q3<-as.numeric(quantile(variable,0.75))
    mild_low<-q1-(1.5*iqr)
    mild_high<-q3+(1.5*iqr)
    new_variable<-variable[variable>mild_low & variable<mild_high]
    return(new_variable)
}

Vui lòng thêm một số giải thích cho câu trả lời của bạn. Tham khảo Cách trả lời .
ejderuby
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.