Bagaimana cara menghapus pencilan dari kumpulan data


98

Saya punya beberapa data multivariat tentang kecantikan vs usia. Usia berkisar dari 20-40 dengan interval 2 (20, 22, 24 .... 40), dan untuk setiap catatan data, mereka diberi peringkat usia dan kecantikan 1-5. Ketika saya membuat diagram kotak dari data ini (usia di sepanjang sumbu X, peringkat kecantikan di sumbu Y), ada beberapa pencilan yang diplot di luar kumis setiap kotak.

Saya ingin menghapus pencilan ini dari bingkai data itu sendiri, tetapi saya tidak yakin bagaimana R menghitung pencilan untuk plot kotaknya. Berikut adalah contoh tampilan data saya. masukkan deskripsi gambar di sini


2
The boxplotmengembalikan fungsi outlier (antara statistik lainnya) tak terlihat. Coba foo <- boxplot(...); foodan baca ?boxplotuntuk memahami hasilnya.
Joshua Ulrich

Anda harus mengedit pertanyaan Anda sesuai dengan komentar yang Anda berikan pada jawaban @ Prasad!
aL3xa

@ aL3xa: ada di kalimat pertama paragraf kedua.
Joshua Ulrich


Bisakah Anda mengirim tautan ke data?
pula kata

Jawaban:


120

Oke, Anda harus menerapkan sesuatu seperti ini ke dataset Anda. Jangan mengganti & menyimpan atau Anda akan menghancurkan data Anda! Dan, btw, Anda seharusnya (hampir) tidak pernah menghapus pencilan dari data Anda:

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
}

Untuk melihatnya beraksi:

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

Dan sekali lagi, Anda tidak boleh melakukan ini sendiri, outlier memang seharusnya begitu! =)

EDIT: Saya menambahkan na.rm = TRUEsebagai default.

EDIT2:quantile Fungsi dihapus , ditambahkan langganan, karenanya membuat fungsi lebih cepat! =)

masukkan deskripsi gambar di sini


Terima kasih untuk bantuannya! Saya akan berpikir jika R mampu mengeluarkan outlier di boxplot, saya tidak perlu melakukan perhitungan perantara ini. Sedangkan untuk menghapus pencilan, ini hanya untuk penugasan.
Dan Q

3
Oke, saya melewatkan sesuatu di sini. Anda ingin menghapus pencilan dari data, sehingga Anda dapat memplotnya dengan boxplot. Itu bisa diatur, dan Anda harus menandai jawaban @ Prasad kalau begitu, karena menjawab pertanyaan Anda. Jika Anda ingin mengecualikan pencilan dengan menggunakan "aturan pencilan" q +/- (1.5 * H), maka jalankan beberapa analisis, lalu gunakan fungsi ini. BTW, saya melakukan ini dari awal, tanpa Googling, jadi ada kemungkinan saya telah menemukan kembali roda dengan fungsi saya ini ...
aL3xa

10
Anda tidak boleh mengajukan pertanyaan tugas di stackoverflow!
hadley

7
Apakah itu berarti kita juga tidak harus menjawabnya? =)
aL3xa

5
"pencilan hanya dimaksudkan untuk menjadi"? Belum tentu. Mereka mungkin berasal dari kesalahan ukuran, dan harus ditinjau secara menyeluruh. Ketika outlier terlalu besar, itu mungkin berarti sesuatu, atau tidak terlalu banyak. Itulah mengapa (setidaknya dalam biologi) median biasanya menunjukkan lebih banyak tentang suatu populasi daripada mean.
Rodrigo

133

Tidak ada yang memposting jawaban paling sederhana:

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

Lihat juga ini: http://www.r-statistics.com/2011/01/how-to-label-all-the-outliers-in-a-boxplot/


4
Sangat elegan. Terima kasih. Namun perlu hati-hati jika pendistribusiannya memiliki lebih dari satu mode dan outlier memang hanya sedikit dan tersebar.
KarthikS

Akan sangat bagus jika Anda bisa mendapatkan indeksnya dalam kumpulan data. Cara Anda selesai akan memfilter berdasarkan nilai data. Jika box plot juga melakukan pengelompokan, belum tentu nilai data yang sama akan outlier di masing-masing kelompok
adam

2
Penting juga untuk disebutkan bahwa itu tidak mengubah kumpulan data. Ini hanyalah metode pemfilteran. Jadi, jika Anda bermaksud untuk menggunakan dataset tanpa pencilan, tetapkan ke variabel. misalnyaresult = x[!x %in% boxplot.stats(x)$out]
Victor Augusto

Hanya memiliki satu baris kode tidak selalu berarti itu sederhana! Tidak selalu mudah untuk memahami kode satu baris, khususnya untuk pemula, dan tanpa komentar.
PeyM87

29

Gunakan outline = FALSEsebagai opsi saat Anda membuat plot kotak (baca bantuannya!).

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

masukkan deskripsi gambar di sini


4
memang, ini akan menghapus pencilan dari boxplot itu sendiri, tetapi saya ingin menghapus pencilan dari bingkai data.
Dan Q

2
Begitu, lalu seperti yang dikatakan @Joshua, Anda perlu melihat data yang dikembalikan oleh fungsi boxplot (khususnya item outdan groupdalam daftar).
Prasad Chalasani

16

Fungsi boxplot mengembalikan nilai yang digunakan untuk melakukan plotting (yang kemudian dilakukan oleh 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

Saya sengaja tidak menjawab pertanyaan tertentu karena saya menganggapnya sebagai malpraktek statistik untuk menghilangkan "pencilan". Saya menganggap praktik yang dapat diterima untuk tidak memplotnya dalam plot kotak, tetapi menghapusnya hanya karena melebihi sejumlah deviasi standar atau beberapa lebar antar-kuartil adalah pemecahan rekaman pengamatan yang sistematis dan tidak ilmiah.


4
Nah, mengabaikan pertanyaan tanpa mengetahui mengapa pertanyaan itu diajukan juga bukan praktik yang baik. Ya, tidak baik untuk menghapus 'pencilan' dari data tetapi terkadang Anda memerlukan data tanpa pencilan untuk tugas tertentu. Dalam tugas statistik yang saya miliki baru-baru ini, kami harus memvisualisasikan satu set tanpa pencilannya untuk menentukan model regresi terbaik yang akan digunakan untuk data. Jadi disana!
Alex Essilfie

4
Saya tidak menganggap nasihat yang mungkin Anda dapatkan dalam hal ini tentang "menentukan model regresi terbaik" menjadi sangat persuasif. Sebaliknya, jika Anda perlu menghapus pencilan untuk tujuan yang dinyatakan secara samar-samar itu, maka saya pikir itu mencerminkan buruk pada orang yang menasihatinya daripada menjadi bukti ketidakabsahan posisi saya.
IRTFM

Saya rasa itu sah ketika Anda tahu Anda menghilangkan "kebisingan". terutama pada data fisiologis.
roscoe1895

Iya. Jika Anda memiliki alasan kuat untuk percaya bahwa proses terpisah menciptakan sinyal, itu adalah pembenaran untuk penghapusan dari data.
IRTFM

9

Saya mencari paket yang terkait dengan penghapusan pencilan, dan menemukan paket ini (secara mengejutkan disebut "pencilan"!): Https://cran.r-project.org/web/packages/outliers/outliers.pdf
jika Anda melewatinya, Anda lihat berbagai cara untuk menghilangkan pencilan dan di antara mereka saya menemukan yang rm.outlierpaling nyaman untuk digunakan dan seperti yang dikatakan di tautan di atas: "Jika pencilan dideteksi dan dikonfirmasi oleh uji statistik, fungsi ini dapat menghapusnya atau mengganti dengan mean sampel atau median" dan juga berikut adalah bagian penggunaan dari sumber yang sama:
" Penggunaan

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

Argumen
x kumpulan data, paling sering berupa vektor. Jika argumen adalah kerangka data, maka pencilan dihapus dari setiap kolom dengan sapply. Perilaku yang sama diterapkan dengan menerapkan ketika matriks diberikan.
fill Jika disetel ke TRUE, median atau mean ditempatkan sebagai pengganti outlier. Jika tidak, pencilan akan dihapus begitu saja.
median Jika disetel ke TRUE, median digunakan sebagai pengganti mean dalam penggantian pencilan. berlawanan jika disetel ke TRUE, memberikan nilai berlawanan (jika nilai terbesar memiliki selisih maksimum dari mean, itu menjadi terkecil dan sebaliknya) "


Ini tampak hebat, tetapi jika Anda memiliki kolom deret waktu di bingkai data Anda, itu mengubah deret waktu.
PeyM87

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

Saya merasa ini sangat mudah untuk menghilangkan pencilan. Dalam contoh di atas saya hanya mengekstrak 2 persentil menjadi 98 persentil dari nilai atribut.


5

Tidak akan:

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

menyelesaikan tugas ini dengan cukup mudah?


4

Menambahkan ke saran @sefarkas dan menggunakan kuantil sebagai cut-off, seseorang dapat menjelajahi opsi berikut:

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

Ini akan menghapus poin poin di luar kuantil ke-99. Perhatian harus diberikan seperti yang dikatakan aL3Xa tentang menjaga pencilan. Ini harus dihapus hanya untuk mendapatkan pandangan konservatif alternatif dari data.


apakah itu 0.91atau 0.99? seperti dalam mydata$var < quantile(mydata$var, probs=c(.01, .91))[1])ataumydata$var < quantile(mydata$var, probs=c(.01, .99))[1])
Komal Rathi

Jika Anda memiliki alasan khusus untuk menggunakan persentil ke-91, bukan persentil ke-99, Anda dapat menggunakannya. Ini hanya heuristik
KarthikS

1

Salah satu cara untuk melakukannya adalah

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

atau

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

Pencilan sangat mirip dengan puncak, sehingga detektor puncak dapat berguna untuk mengidentifikasi pencilan. Metode yang dijelaskan di sini memiliki kinerja yang cukup baik dengan menggunakan skor-z. Bagian animasi bagian bawah halaman menggambarkan metode pensinyalan pada pencilan, atau puncak.

Puncak tidak selalu sama dengan pencilan, tetapi sering serupa.

Contoh ditunjukkan di sini: Dataset ini dibaca dari sensor melalui komunikasi serial. Kesalahan komunikasi serial sesekali, kesalahan sensor atau keduanya menyebabkan poin data yang salah dan berulang. Tidak ada nilai statistik dalam hal ini. Mereka bisa dibilang bukan pencilan, mereka adalah kesalahan. Detektor puncak skor-z mampu memberi sinyal pada titik data palsu dan menghasilkan kumpulan data yang bersih:masukkan deskripsi gambar di sini


-1

Coba ini. Beri makan variabel Anda di fungsi dan simpan output daya di variabel yang akan berisi pencilan yang dihapus

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

Tolong tambahkan penjelasan untuk jawaban Anda. Lihat Bagaimana menjawabnya .
ejderuby
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.