Abaikan pencilan di boxplot ggplot2

132

Bagaimana saya mengabaikan outlier di boxplot ggplot2? Saya tidak hanya ingin mereka menghilang (yaitu outlier.size = 0), tetapi saya ingin mereka diabaikan sehingga sumbu y menunjukkan skala untuk menunjukkan 1/3 persentil. Pencilan saya menyebabkan "kotak" menyusut begitu kecil sehingga praktis sebuah garis. Apakah ada beberapa teknik untuk mengatasi ini?

Edit Ini contohnya:

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

masukkan deskripsi gambar di sini

SFun28
sumber
Beberapa data sampel dan contoh yang dapat direproduksi akan memudahkan Anda.
Andrie
3
file saya 200 mcg! Ambil saja dataset mana pun yang memiliki banyak titik data antara kuantil ke-1 dan ke-3 dan beberapa outlier (Anda hanya perlu 1). Jika outlier jauh dari 1st / 3rd maka tentu kotak akan menyusut untuk mengakomodasi outlier
SFun28
Ya, itulah yang ada dalam pikiran saya. Buat dataset seperti itu dan gunakan dput () untuk mempostingnya di sini bersama dengan pernyataan ggplot () yang Anda gunakan. Bantu kami untuk membantu Anda.
Andrie
Tidak bisakah Anda hanya mengubah batas sumbu y untuk "memperbesar" pada bagian sumbu y yang Anda minati?
Gavin Simpson
2
biarkan aku melihat .... Oh ya, maaf. Lakukan saja fivenum()pada data untuk mengekstrak apa, IIRC, digunakan untuk engsel atas dan bawah pada boxplots dan gunakan output itu dalam scale_y_continuous()panggilan yang ditunjukkan @Ritchie. Ini dapat diotomatisasi dengan sangat mudah menggunakan alat R dan ggplot menyediakan. Jika Anda juga perlu memasukkan kumis, pertimbangkan boxplot.stats()untuk menggunakan untuk mendapatkan batas atas dan bawah untuk kumis dan gunakan kemudian scale_y_continuous().
Gavin Simpson

Jawaban:

141

Berikut ini adalah solusi menggunakan 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)
Ramnath
sumber
15
+1 untuk perhitungan otomatis, +1 untuk menggunakan coord_cartesian untuk memperbesar daripada mengecualikan data
Ben Bolker
2
@ Ben - Anda memiliki dua akun? =) @Ramnath - ini adalah solusi yang sangat elegan
SFun28
7
Dengan menggunakan metode di atas, batas mungkin dibiaskan oleh ekstrem kecil di satu sisi dan ekstrem besar di sisi lain, misalnya ylim <- c(-0.1, 1000) * 1.05memberi [1] 0.105 1050. Untuk mendapatkan batas yang sama di sekitar rata-rata yang bisa Anda gunakan ylim + c(-0.05, 0.05) * diff(ylim) / 2. Lebih cantik menurut saya.
Bram Visser
2
@Ramnath apa yang $ stats [c (1,5)] lakukan?
lukeg
3
Ini tidak berfungsi jika Anda menggunakan facet_grid(). Maka Anda memiliki banyak boxplots, bukan satu. Dengan demikian Anda tidak mendapatkan batas yang tepat.
WitheShadow
204

Gunakan geom_boxplot(outlier.shape = NA)untuk tidak menampilkan outlier danscale_y_continuous(limits = c(lower, upper)) untuk mengubah batas sumbu.

Sebuah contoh.

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

Sebenarnya, seperti yang ditunjukkan Ramnath dalam jawabannya (dan Andrie juga dalam komentar), lebih masuk akal untuk memotong skala setelah Anda menghitung statistik, via coord_cartesian.

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

(Anda mungkin masih harus menggunakan scale_y_continuousuntuk memperbaiki istirahat sumbu.)

Richie Cotton
sumber
1
Jadi saya harus menghitung lebih rendah / atas - mungkin dengan menghitung persentil 1/3? Berarti tidak ada cara auto-ajaib untuk memberitahu gg-plot2 untuk mengabaikan outlier dan skala secara cerdas?
SFun28
38
Hati-hati dengan scale_y_continuous (batas = ...) Ini akan menghapus data yang berada di luar batas dan kemudian melakukan perhitungan statistik. Dengan kata lain rerata dan ringkasan lainnya akan terpengaruh. Jika ini yang Anda inginkan, baguslah. Alternatifnya adalah menggunakan coord_cartesian (limit = ...) - ini 'memperbesar' tanpa menghapus data atau memengaruhi ringkasan.
Andrie
@ Andrie - terima kasih! Saya tidak ingin ringkasan jahat dan lainnya terpengaruh.
SFun28
1
coord_cartesian()tidak bermain dengan baik coord_flip(), dalam pengalaman saya, jadi saya lebih suka scale_y_continuous().
PatrickT
1
Ini solusi terbaik. Alasan saya ingin menyembunyikan outlier adalah karena saya juga merencanakan titik jitter dengan geom_jitter. Dalam hal ini outlier hanya menghalangi dan membuatnya terlihat seperti ada lebih banyak poin daripada yang seharusnya.
williamsurles
14

Saya memiliki masalah yang sama dan menghitung nilai untuk Q1, Q2, median, ymin, ymax menggunakan 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

Hasilnya adalah boxplot tanpa outlier. masukkan deskripsi gambar di sini

Matthias Munz
sumber
9

Satu ide adalah menangkan data dalam prosedur dua langkah:

  1. jalankan pass pertama, pelajari batasannya, mis. potongan pada persentil tertentu, atau standar deviasi N di atas rata-rata, atau ...

  2. dalam pass kedua, atur nilai di luar batas yang diberikan ke nilai batas itu

Saya harus menekankan bahwa ini adalah metode kuno yang seharusnya didominasi oleh teknik-teknik canggih yang lebih modern, tetapi Anda masih sering menemukannya.

Dirk Eddelbuettel
sumber
1
Siapa pun yang turun secara diam-diam : tinggalkan komentar untuk menjelaskan alasannya .
Dirk Eddelbuettel
Bukan saya. Hanya ingin menambahkan bahwa memiliki kumis yang berhenti di persentil (biasanya 10 dan 90) tampaknya sangat umum dengan data lingkungan.
Richie Cotton
Saya adalah +1 yang diam , dan berharap saya memiliki yang lain untuk ditawarkan. Kemenangan hampir selalu dilakukan dalam ekonomi + keuangan. Jika SFun memiliki outlier yang merusak visualiasi data, saya ingin tahu apa pengaruhnya terhadap analisis data.
Richard Herron
sedang membaca kembali posting ini, Anda menyebutkan bahwa windsorizing adalah teknik yang lebih tua .... apa yang akan menjadi teknik yang lebih modern?
SFun28
1
Secara umum, metode yang kuat sebagai pengembangan dari 30+ tahun terakhir.
Dirk Eddelbuettel
2

Opsi "coef" dari fungsi geom_boxplot memungkinkan untuk mengubah batas outlier dalam hal rentang interkuartil. Opsi ini didokumentasikan untuk fungsi stat_boxplot. Untuk menonaktifkan pencilan (dengan kata lain mereka diperlakukan sebagai data biasa), seseorang dapat menggunakan nilai default 1,5 daripada menentukan nilai cutoff yang sangat tinggi:

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)
Eeckart
sumber
3
Itu hanya memperpanjang kumis, itu tidak mengubah
skala
2

Jika Anda ingin memaksa kumis untuk memperluas ke nilai max dan min, Anda dapat mengubah coefargumen. Nilai default untuk coefadalah 1,5 (yaitu panjang kumis standar adalah 1,5 kali 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)

gambar p0

gambar p1

IggyM
sumber
2

Ipaper :: geom_boxplot2 adalah yang Anda inginkan.

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

masukkan deskripsi gambar di sini

Dongdong Kong
sumber
Terima kasih!! Diuji dengan data saya, bekerja dengan sempurna! Saya akan merekomendasikan solusi ini, walaupun saya tidak yakin tentang stabilitas / dukungan lama dari hal-hal github.
Gildas