วิธีลบค่าผิดปกติออกจากชุดข้อมูล


101

ฉันมีข้อมูลหลายตัวแปรเกี่ยวกับความงามเทียบกับวัย อายุมีตั้งแต่ 20-40 ช่วง 2 (20, 22, 24 .... 40) และสำหรับการบันทึกข้อมูลแต่ละครั้งจะได้รับอายุและคะแนนความงามตั้งแต่ 1-5 เมื่อฉันทำบ็อกซ์พล็อตของข้อมูลนี้ (อายุในแกน X, การให้คะแนนความงามในแกน Y) มีค่าผิดปกติบางอย่างที่พล็อตอยู่นอกหนวดของแต่ละกล่อง

ฉันต้องการลบค่าผิดปกติเหล่านี้ออกจากกรอบข้อมูล แต่ฉันไม่แน่ใจว่า R คำนวณค่าผิดปกติสำหรับพล็อตกล่องอย่างไร ด้านล่างนี้คือตัวอย่างลักษณะข้อมูลของฉัน ป้อนคำอธิบายภาพที่นี่


2
boxplotฟังก์ชันส่งกลับค่าผิดปกติ (ในสถิติอื่น ๆ ) ลูกหูลูกตา ลองfoo <- boxplot(...); fooอ่าน?boxplotเพื่อทำความเข้าใจผลลัพธ์
Joshua Ulrich

คุณควรแก้ไขคำถามของคุณตามความคิดเห็นที่คุณให้ไว้ในคำตอบของ @ Prasad!
aL3xa

@ aL3xa: อยู่ในประโยคแรกของย่อหน้าที่สอง
Joshua Ulrich

24
เกี่ยวข้อง: davidmlane.com/ben/outlier.gif
eyjo

คุณสามารถส่งลิงค์ไปยังข้อมูลได้หรือไม่?
คำว่า

คำตอบ:


120

ตกลงคุณควรใช้สิ่งนี้กับชุดข้อมูลของคุณ อย่าแทนที่และบันทึกมิฉะนั้นคุณจะทำลายข้อมูลของคุณ! และคุณไม่ควร (เกือบ) ลบค่าผิดปกติออกจากข้อมูลของคุณ:

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
}

หากต้องการดูการใช้งานจริง:

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

และอีกครั้งที่คุณไม่ควรทำสิ่งนี้ด้วยตัวคุณเองค่าผิดปกติควรจะเป็น! =)

แก้ไข:ฉันเพิ่มna.rm = TRUEเป็นค่าเริ่มต้น

EDIT2:quantileฟังก์ชันที่ถูกลบออกเพิ่มการห้อยลงมาจึงทำให้ฟังก์ชันเร็วขึ้น! =)

ป้อนคำอธิบายภาพที่นี่


ขอบคุณสำหรับความช่วยเหลือ! ฉันจะคิดว่าถ้า R สามารถส่งออกค่าผิดปกติใน boxplot ฉันไม่ควรต้องคำนวณตัวกลางเหล่านี้ สำหรับการลบค่าผิดปกตินี้เป็นเพียงการมอบหมายงานเท่านั้น
Dan Q

3
ตกลงฉันขาดอะไรที่นี่ boxplotคุณต้องการที่จะลบค่าผิดปกติจากข้อมูลเพื่อให้คุณสามารถพล็อตพวกเขาด้วย นั่นสามารถจัดการได้และคุณควรทำเครื่องหมายคำตอบของ @ ปราสาดตั้งแต่นั้นตอบคำถามของคุณ หากคุณต้องการยกเว้นค่าผิดปกติโดยใช้ "กฎค่าผิดปกติ" q +/- (1.5 * H)ให้ทำการวิเคราะห์บางส่วนจากนั้นใช้ฟังก์ชันนี้ BTW ฉันทำสิ่งนี้ตั้งแต่เริ่มต้นโดยไม่มี Googling ดังนั้นมีโอกาสที่ฉันจะคิดค้นล้อใหม่ด้วยฟังก์ชั่นของฉัน ...
aL3xa

10
คุณไม่ควรถามคำถามเกี่ยวกับการมอบหมายใน stackoverflow!
hadley

7
นั่นหมายความว่าเราไม่ควรตอบเช่นกัน? =)
aL3xa

5
"ค่าผิดปกติมีไว้เพื่อเป็น"? ไม่จำเป็น. อาจมาจากข้อผิดพลาดในการวัดและต้องได้รับการตรวจสอบอย่างละเอียด เมื่อค่าผิดปกติใหญ่เกินไปอาจหมายถึงบางอย่างหรือไม่มากก็ได้ นั่นเป็นเหตุผลว่าทำไม (อย่างน้อยในทางชีววิทยา) ค่ามัธยฐานมักพูดเกี่ยวกับประชากรมากกว่าค่าเฉลี่ย
Rodrigo

137

ไม่มีใครโพสต์คำตอบที่ง่ายที่สุด:

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

ดูสิ่งนี้ได้ที่http://www.r-statistics.com/2011/01/how-to-label-all-the-outliers-in-a-boxplot/


4
สง่างามจริงๆ. ขอบคุณ. แต่ต้องระวังหากการกระจายมีมากกว่าหนึ่งโหมดและค่าผิดปกติมีเพียงไม่กี่โหมดและกระจัดกระจาย
KarthikS

มันจะดีมากถ้าคุณสามารถรับดัชนีของพวกเขาในชุดข้อมูลได้ วิธีที่คุณทำจะกรองตามค่าข้อมูล หากพล็อตบ็อกซ์กำลังทำการจัดกลุ่มค่าข้อมูลที่ไม่จำเป็นต้องเหมือนกันจะเป็นค่าผิดปกติในแต่ละกลุ่ม
ดัม

2
สิ่งสำคัญคือต้องระบุด้วยว่าจะไม่เปลี่ยนชุดข้อมูล นี่เป็นเพียงวิธีการกรองเท่านั้น ดังนั้นหากคุณตั้งใจจะใช้ชุดข้อมูลโดยไม่มีค่าผิดปกติกำหนดให้กับตัวแปร เช่นresult = x[!x %in% boxplot.stats(x)$out]
Victor Augusto

การมีโค้ดเพียงบรรทัดเดียวไม่ได้แปลว่าจะง่าย! ไม่ใช่เรื่องง่ายเสมอไปที่จะเข้าใจรหัสบรรทัดเดียวโดยเฉพาะสำหรับผู้เริ่มต้นและไม่มีความคิดเห็น
PeyM87

29

ใช้outline = FALSEเป็นตัวเลือกเมื่อคุณทำ boxplot (อ่านวิธีใช้!)

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

ป้อนคำอธิบายภาพที่นี่


4
แน่นอนสิ่งนี้จะลบค่าผิดปกติออกจาก boxplot เอง แต่ฉันต้องการลบค่าผิดปกติออกจาก data frame
Dan Q

2
ฉันเห็นแล้วอย่างที่ @Joshua กล่าวว่าคุณต้องดูข้อมูลที่ส่งคืนโดยฟังก์ชัน boxplot (โดยเฉพาะoutและgroupรายการในรายการ)
ปราสาทชลาสนี

16

ฟังก์ชัน boxplot จะส่งคืนค่าที่ใช้ในการลงจุด (ซึ่งจริงแล้ว 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

ฉันไม่ได้ตั้งใจที่จะตอบคำถามที่เจาะจงเพราะฉันคิดว่าเป็นการทุจริตต่อหน้าที่ทางสถิติเพื่อลบ "ค่าผิดปกติ" ฉันคิดว่าเป็นวิธีปฏิบัติที่ยอมรับได้ที่จะไม่วางพล็อตไว้ในบ็อกซ์พล็อต แต่การลบออกเพียงเพราะค่าเบี่ยงเบนมาตรฐานเกินจำนวนหรือความกว้างระหว่างควอร์ไทล์บางส่วนเป็นการบิดเบือนบันทึกเชิงสังเกตอย่างเป็นระบบและไม่ถูกต้องตามหลักวิทยาศาสตร์


4
การหลีกเลี่ยงคำถามโดยไม่ทราบว่าเหตุใดจึงถามคำถามจึงไม่ใช่แนวทางปฏิบัติที่ดีเช่นกัน ใช่การลบ 'ค่าผิดปกติ' ออกจากข้อมูลไม่ใช่เรื่องดี แต่บางครั้งคุณต้องการข้อมูลโดยไม่มีค่าผิดปกติสำหรับงานบางอย่าง ในการกำหนดสถิติเมื่อเร็ว ๆ นี้เราต้องเห็นภาพชุดที่ไม่มีค่าผิดปกติเพื่อกำหนดรูปแบบการถดถอยที่ดีที่สุดที่จะใช้สำหรับข้อมูล ที่นั่น!
Alex Essilfie

4
ฉันไม่ได้พิจารณาคำแนะนำที่คุณอาจได้รับเกี่ยวกับ "กำหนดรูปแบบการถดถอยที่ดีที่สุด" เพื่อโน้มน้าวใจโดยเฉพาะ แต่ถ้าคุณต้องการลบค่าผิดปกติสำหรับวัตถุประสงค์ที่ระบุไว้อย่างคลุมเครือฉันคิดว่ามันสะท้อนให้เห็นถึงผู้ที่ให้คำแนะนำไม่ดีแทนที่จะเป็นหลักฐานว่าตำแหน่งของฉันไม่ถูกต้อง
IRTFM

ฉันเดาว่ามันถูกต้องเมื่อคุณรู้ว่าคุณกำลังลบ "เสียงรบกวน" โดยเฉพาะอย่างยิ่งในข้อมูลทางสรีรวิทยา
roscoe1895

ใช่. หากคุณมีเหตุผลที่ดีที่จะเชื่อว่ากระบวนการที่แยกจากกันสร้างสัญญาณนั้นเป็นเหตุผลที่สมควรที่จะลบออกจากข้อมูล
IRTFM

9

ฉันค้นหาแพ็คเกจที่เกี่ยวข้องกับการลบค่าผิดปกติและพบแพ็คเกจนี้ (เรียกว่า "ค่าผิดปกติ"!): https://cran.r-project.org/web/packages/outliers/outliers.pdf
หากคุณทำผ่าน ดูวิธีต่างๆในการลบค่าผิดปกติและฉันพบว่าrm.outlierวิธีที่สะดวกที่สุดในการใช้และตามที่ระบุไว้ในลิงก์ด้านบน: "หากตรวจพบค่าผิดปกติและยืนยันโดยการทดสอบทางสถิติฟังก์ชันนี้สามารถลบหรือแทนที่ด้วยค่าเฉลี่ยตัวอย่างหรือค่ามัธยฐาน" และนี่คือส่วนการใช้งานจากแหล่งเดียวกัน:
" การใช้งาน

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

อาร์กิวเมนต์
x ชุดข้อมูลมักเป็นเวกเตอร์ ถ้าอาร์กิวเมนต์เป็น dataframe ค่าผิดปกติจะถูกลบออกจากแต่ละคอลัมน์โดย sapply พฤติกรรมเดียวกันนี้ถูกนำไปใช้โดยใช้เมื่อกำหนดเมทริกซ์
เติม หากตั้งค่าเป็น TRUE ค่ามัธยฐานหรือค่าเฉลี่ยจะถูกวางไว้แทนค่าผิดปกติ มิฉะนั้นค่าผิดปกติจะถูกลบออกไป
มัธยฐาน หากตั้งค่าเป็น TRUE ค่ามัธยฐานจะถูกใช้แทนค่าเฉลี่ยในการแทนที่ค่าผิดปกติ ตรงข้ามถ้าตั้งค่าเป็น TRUE จะให้ค่าตรงกันข้าม (หากค่าที่ใหญ่ที่สุดมีความแตกต่างสูงสุดจากค่าเฉลี่ยจะให้น้อยที่สุดและในทางกลับกัน) "


ดูเหมือนจะดี แต่ถ้าคุณมีคอลัมน์อนุกรมเวลาในกรอบข้อมูลของคุณก็จะเปลี่ยนอนุกรมเวลา
PeyM87

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

ฉันพบว่าสิ่งนี้ง่ายมากที่จะลบค่าผิดปกติ ในตัวอย่างข้างต้นฉันแค่แยกค่าแอตทริบิวต์ 2 เปอร์เซ็นไทล์ถึง 98 เปอร์เซ็นไทล์


5

จะไม่:

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

ทำงานนี้ให้สำเร็จได้อย่างง่ายดาย?


4

การเพิ่มข้อเสนอแนะของ @sefarkas และการใช้ quantile เป็นตัวตัดหนึ่งสามารถสำรวจตัวเลือกต่อไปนี้:

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

การดำเนินการนี้จะลบคะแนนที่เกินกว่าจำนวนที่ 99 ควรใช้ความระมัดระวังเช่นเดียวกับที่ aL3Xa พูดเกี่ยวกับการรักษาค่าผิดปกติ ควรลบออกเพื่อรับมุมมองแบบอนุรักษ์นิยมทางเลือกของข้อมูลเท่านั้น


มัน0.91หรือ0.99? ในmydata$var < quantile(mydata$var, probs=c(.01, .91))[1])หรือmydata$var < quantile(mydata$var, probs=c(.01, .99))[1])
Komal Rathi

หากคุณมีเหตุผลเฉพาะที่จะใช้เปอร์เซ็นไทล์ที่ 91 แทนเปอร์เซ็นไทล์ที่ 99 คุณสามารถใช้ได้ เป็นเพียงการฮิวริสติกเท่านั้น
KarthikS

1

1 วิธีที่ทำได้คือ

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

หรือ

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

ค่าผิดปกติค่อนข้างคล้ายกับจุดสูงสุดดังนั้นเครื่องตรวจจับจุดสูงสุดจึงมีประโยชน์ในการระบุค่าผิดปกติ วิธีการที่อธิบายไว้ที่นี่มีประสิทธิภาพค่อนข้างดีเมื่อใช้คะแนน z ภาพเคลื่อนไหวส่วนหนึ่งลงไปในหน้าแสดงวิธีการส่งสัญญาณเกี่ยวกับค่าผิดปกติหรือจุดสูงสุด

Peaks ไม่เหมือนกับค่าผิดปกติเสมอไป แต่มักจะคล้ายกัน

ตัวอย่างแสดงที่นี่: ชุดข้อมูลนี้อ่านจากเซ็นเซอร์ผ่านการสื่อสารแบบอนุกรม ข้อผิดพลาดในการสื่อสารแบบอนุกรมเป็นครั้งคราวข้อผิดพลาดของเซ็นเซอร์หรือทั้งสองอย่างนำไปสู่จุดข้อมูลที่ผิดพลาดซ้ำ ๆ อย่างชัดเจน ไม่มีค่าทางสถิติในประเด็นเหล่านี้ เนื้อหาเหล่านี้ไม่ใช่สิ่งผิดปกติ แต่เป็นข้อผิดพลาด เครื่องตรวจจับจุดสูงสุด z-score สามารถส่งสัญญาณไปยังจุดข้อมูลปลอมและสร้างชุดข้อมูลผลลัพธ์ที่สะอาด:ป้อนคำอธิบายภาพที่นี่


-1

ลองทำตามนี้ ป้อนตัวแปรของคุณในฟังก์ชันและบันทึก o / p ในตัวแปรซึ่งจะมีค่าผิดปกติที่ถูกลบออก

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

โปรดเพิ่มคำอธิบายในคำตอบของคุณ อ้างถึงวิธีที่จะตอบ
ejderuby
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.