ละเว้นค่าผิดปกติใน ggplot2 boxplot


132

ฉันจะเพิกเฉยต่อค่าผิดปกติใน ggplot2 boxplot ได้อย่างไร ฉันไม่เพียงต้องการให้พวกมันหายไป (เช่น outlier.size = 0) แต่ฉันต้องการให้พวกเขาถูกละเว้นเพื่อให้แกน y แสดงเปอร์เซ็นต์ไทล์ที่ 1/3 ค่าผิดปกติของฉันทำให้ "กล่อง" หดเล็กลงจนแทบจะเป็นเส้น มีเทคนิคบางอย่างในการจัดการกับสิ่งนี้หรือไม่?

แก้ไข นี่คือตัวอย่าง:

y = c(.01, .02, .03, .04, .05, .06, .07, .08, .09, .5, -.6)
qplot(1, y, geom="boxplot")

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


ข้อมูลตัวอย่างบางส่วนและตัวอย่างที่ทำซ้ำได้จะช่วยให้คุณง่ายขึ้น
Andrie

3
ไฟล์ของฉันคือ 200 meg! เพียงใช้ชุดข้อมูลใด ๆ ที่มีจุดข้อมูลจำนวนมากระหว่างควอนไทล์ที่ 1 และ 3 และค่าผิดปกติเพียงเล็กน้อย (คุณต้องการเพียง 1) หากค่าผิดปกติอยู่ห่างจากวันที่
1/3

ใช่นั่นคือสิ่งที่ฉันคิด สร้างชุดข้อมูลดังกล่าวและใช้ dput () เพื่อโพสต์ไว้ที่นี่พร้อมกับคำสั่ง ggplot () ที่คุณใช้ ช่วยให้เราช่วยคุณ
Andrie

คุณไม่สามารถเปลี่ยนขีด จำกัด แกน y เป็น "ซูม" ในส่วนของแกน y ที่คุณสนใจได้หรือไม่?
Gavin Simpson

2
ให้ฉันดู .... โอ้ใช่ขอโทษ เพียงแค่ทำfivenum()ข้อมูลเพื่อแยกสิ่งที่ IIRC ใช้สำหรับบานพับบนและล่างของ boxplots และใช้เอาต์พุตนั้นในการscale_y_continuous()โทรที่ @Ritchie แสดง สิ่งนี้สามารถทำได้โดยอัตโนมัติอย่างง่ายดายโดยใช้เครื่องมือที่ R และ ggplot มีให้ หากคุณต้องการที่จะรวมถึงเคราเช่นกันพิจารณาใช้boxplot.stats()จะได้รับขีด จำกัด scale_y_continuous()บนและล่างสำหรับเคราและใช้แล้ว
Gavin Simpson

คำตอบ:


141

นี่คือวิธีแก้ปัญหาโดยใช้ boxplot.stats

# create a dummy data frame with outliers
df = data.frame(y = c(-100, rnorm(100), 100))

# create boxplot that includes outliers
p0 = ggplot(df, aes(y = y)) + geom_boxplot(aes(x = factor(1)))


# compute lower and upper whiskers
ylim1 = boxplot.stats(df$y)$stats[c(1, 5)]

# scale y limits based on ylim1
p1 = p0 + coord_cartesian(ylim = ylim1*1.05)

15
+1 สำหรับการคำนวณอัตโนมัติ +1 สำหรับการใช้ผู้ประสานงานเพื่อซูมแทนที่จะไม่รวมข้อมูล
Ben Bolker

2
@ เบ็น - คุณมีสองบัญชี? =) @Ramnath - นี่เป็นทางออกที่ยอดเยี่ยมจริงๆ
SFun28

7
โดยใช้วิธีการดังกล่าวข้างต้นข้อ จำกัด อาจได้รับ biassed โดยมากมีขนาดเล็กในด้านหนึ่งและและรุนแรงขนาดใหญ่ในที่อื่น ๆ เช่นให้ylim <- c(-0.1, 1000) * 1.05 [1] 0.105 1050เพื่อให้ได้ขีด จำกัด ที่เท่ากันรอบ ๆ ค่าเฉลี่ยที่คุณสามารถylim + c(-0.05, 0.05) * diff(ylim) / 2ใช้ได้ สวยกว่าในความคิดของฉัน
Bram Visser

2
@Ramnath $ stats [c (1,5)] ทำอะไร?
lukeg

3
ไม่ทำงานหากคุณใช้facet_grid(). จากนั้นคุณจะมีบ็อกซ์พล็อตหลายแบบแทนที่จะเป็นแบบเดียว ดังนั้นคุณจะไม่ได้รับขีด จำกัด ที่ถูกต้อง
WitheShadow

204

ใช้geom_boxplot(outlier.shape = NA)เพื่อไม่แสดงค่าผิดปกติและscale_y_continuous(limits = c(lower, upper))เพื่อเปลี่ยนขีด จำกัด แกน

ตัวอย่าง.

n <- 1e4L
dfr <- data.frame(
  y = exp(rlnorm(n)),  #really right-skewed variable
  f = gl(2, n / 2)
)

p <- ggplot(dfr, aes(f, y)) + 
  geom_boxplot()
p   # big outlier causes quartiles to look too slim

p2 <- ggplot(dfr, aes(f, y)) + 
  geom_boxplot(outlier.shape = NA) +
  scale_y_continuous(limits = quantile(dfr$y, c(0.1, 0.9)))
p2  # no outliers plotted, range shifted

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

coord_cartesian(ylim = quantile(dfr$y, c(0.1, 0.9)))

(คุณอาจต้องใช้scale_y_continuousเพื่อแก้ไขการแตกของแกน)


1
ดังนั้นฉันจะต้องคำนวณค่าต่ำ / บน - บางทีโดยการคำนวณเปอร์เซ็นไทล์ที่ 1/3? หมายความว่าไม่มีวิธีมายากลอัตโนมัติที่จะบอกให้ gg-plot2 ละเว้นค่าผิดปกติและปรับขนาดอย่างชาญฉลาด?
SFun28

38
โปรดใช้ความระมัดระวัง scale_y_continuous (ขีด จำกัด = ... ) ซึ่งจะลบข้อมูลที่อยู่นอกขีด จำกัด จากนั้นทำการคำนวณทางสถิติ กล่าวอีกนัยหนึ่งคือค่าเฉลี่ยและบทสรุปอื่น ๆ จะได้รับผลกระทบ ถ้านี่คือสิ่งที่คุณต้องการแล้วล่ะก็เยี่ยมเลย อีกทางเลือกหนึ่งคือการใช้ Coord_cartesian (ขีด จำกัด = ... ) - 'ซูม' นี้โดยไม่ลบข้อมูลหรือส่งผลต่อการสรุป
Andrie

@ แอนดรี - ขอบคุณ! ฉันไม่ต้องการให้ค่าเฉลี่ยและบทสรุปอื่น ๆ ได้รับผลกระทบ
SFun28

1
coord_cartesian()จากcoord_flip()ประสบการณ์ของฉันเล่นได้ไม่ดีฉันจึงชอบscale_y_continuous()มากกว่า
PatrickT

1
นี่คือทางออกที่ดีที่สุด เหตุผลที่ฉันต้องการซ่อนสิ่งแปลกปลอมก็เพราะฉันกำลังวางแผนจุดที่ทำให้ตกใจด้วย geom_jitter ในกรณีนี้ค่าผิดปกติจะเข้ามาขัดขวางและทำให้ดูเหมือนว่ามีคะแนนมากกว่าที่ควรจะมี
williamsurles

14

ฉันมีปัญหาเดียวกันและคำนวณค่าสำหรับ Q1, Q2, median, ymin, ymax ไว้ล่วงหน้าโดยใช้boxplot.stats:

# Load package and generate data
library(ggplot2)
data <- rnorm(100)

# Compute boxplot statistics
stats <- boxplot.stats(data)$stats
df <- data.frame(x="label1", ymin=stats[1], lower=stats[2], middle=stats[3], 
                 upper=stats[4], ymax=stats[5])

# Create plot
p <- ggplot(df, aes(x=x, lower=lower, upper=upper, middle=middle, ymin=ymin, 
                    ymax=ymax)) + 
    geom_boxplot(stat="identity")
p

ผลลัพธ์คือบ็อกซ์พล็อตที่ไม่มีค่าผิดปกติ ป้อนคำอธิบายภาพที่นี่


9

แนวคิดหนึ่งคือการทำให้ข้อมูลชนะหรือปรับขนาดข้อมูลในขั้นตอนสองรอบ:

  1. วิ่งผ่านแรกเรียนรู้ว่าขอบเขตคืออะไรเช่นการตัดที่เปอร์เซ็นต์ไทล์ที่กำหนดหรือค่าเบี่ยงเบนมาตรฐาน N เหนือค่าเฉลี่ยหรือ ...

  2. ในรอบที่สองตั้งค่าเกินขอบเขตที่กำหนดให้กับค่าของขอบเขตนั้น

ฉันควรเน้นว่านี่เป็นวิธีการที่ล้าสมัยซึ่งควรถูกครอบงำด้วยเทคนิคที่ทันสมัยกว่าแต่คุณก็ยังเจอมันมาก


1
ผู้ใดเพียง downvoted เงียบ : ความคิดเห็นลาที่จะอธิบายว่าทำไม
Dirk Eddelbuettel

ไม่ใช่ฉัน แค่อยากจะเพิ่มว่าการมีหนวดที่หยุดที่เปอร์เซ็นไทล์ (โดยปกติคืออันดับที่ 10 และ 90) ดูเหมือนจะเป็นเรื่องปกติมากกับข้อมูลด้านสิ่งแวดล้อม
Richie Cotton

ฉันเป็น+1 ที่เงียบและหวังว่าจะมีอีกสิ่งที่จะนำเสนอ การ Winsorizing มักจะทำใน econ + finance หาก SFun มีค่าผิดปกติที่ทำลายการแสดงข้อมูลฉันสงสัยว่าผลกระทบต่อการวิเคราะห์ข้อมูลคืออะไร
Richard Herron

กำลังอ่านโพสต์นี้อีกครั้งคุณกล่าวว่าการทำวินด์เซอร์เป็นเทคนิคที่เก่ากว่า .... จะมีเทคนิคอะไรที่ทันสมัยกว่านี้อีกบ้าง?
SFun28

1
โดยทั่วไปวิธีการที่แข็งแกร่งเป็นการพัฒนาในช่วง 30 ปีที่ผ่านมา
Dirk Eddelbuettel

2

ตัวเลือก "coef" ของฟังก์ชัน geom_boxplot อนุญาตให้เปลี่ยนจุดตัดค่าผิดปกติในแง่ของช่วงระหว่างควอไทล์ อ็อพชันนี้จัดทำเป็นเอกสารสำหรับฟังก์ชัน stat_boxplot ในการปิดใช้งานค่าผิดปกติ (กล่าวอีกนัยหนึ่งคือถือว่าเป็นข้อมูลปกติ) เราสามารถแทนที่จะใช้ค่าเริ่มต้น 1.5 ระบุค่าตัดที่สูงมาก:

library(ggplot2)
# generate data with outliers:
df = data.frame(x=1, y = c(-10, rnorm(100), 10)) 
# generate plot with increased cutoff for outliers:
ggplot(df, aes(x, y)) + geom_boxplot(coef=1e30)

3
มันแค่ขยายหนวด แต่ก็ไม่ได้ปรับขนาดแผนภูมิ แต่อย่างใด
Moody_Mudskipper

2

หากคุณต้องการบังคับให้หนวดขยายเป็นค่าสูงสุดและต่ำสุดคุณสามารถปรับแต่งcoefอาร์กิวเมนต์ได้ ค่าเริ่มต้นcoefคือ 1.5 (เช่นความยาวเริ่มต้นของหนวดเคราคือ 1.5 เท่าของ IQR)

# Load package and create a dummy data frame with outliers 
#(using example from Ramnath's answer above)
library(ggplot2)
df = data.frame(y = c(-100, rnorm(100), 100))

# create boxplot that includes outliers
p0 = ggplot(df, aes(y = y)) + geom_boxplot(aes(x = factor(1)))

# create boxplot where whiskers extend to max and min values
p1 = ggplot(df, aes(y = y)) + geom_boxplot(aes(x = factor(1)), coef = 500)

ภาพของ p0

ภาพของ p1


2

Ipaper :: geom_boxplot2 คือสิ่งที่คุณต้องการ

# devtools::install_github('kongdd/Ipaper')
library(Ipaper)
library(ggplot2)
p <- ggplot(mpg, aes(class, hwy))
p + geom_boxplot2(width = 0.8, width.errorbar = 0.5)

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


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