Jak usunąć wartości odstające ze zbioru danych

98

Mam kilka wielowymiarowych danych dotyczących urody w zależności od wieku. Wiek waha się od 20 do 40 w odstępach 2 (20, 22, 24 ... 40), a dla każdego rekordu danych otrzymuje się wiek i ocenę urody od 1 do 5. Kiedy robię wykresy pudełkowe tych danych (wiek na osi X, oceny urody na osi Y), poza wąsami każdego pudełka wykreślono pewne wartości odstające.

Chcę usunąć te wartości odstające z samej ramki danych, ale nie jestem pewien, jak R oblicza wartości odstające dla swoich wykresów pudełkowych. Poniżej znajduje się przykład tego, jak mogą wyglądać moje dane. wprowadź opis obrazu tutaj

Dan Q
źródło
2
boxplotZwraca odstających (między innymi statystykami) niewidocznie. Spróbuj foo <- boxplot(...); fooi przeczytaj, ?boxplotaby zrozumieć wynik.
Joshua Ulrich
Powinieneś edytować swoje pytanie zgodnie z komentarzem, który dodałeś do odpowiedzi @ Prasad!
aL3xa
@ aL3xa: znajduje się w pierwszym zdaniu drugiego akapitu.
Joshua Ulrich
Czy możesz wysłać link do danych?
słowa z

Odpowiedzi:

120

OK, powinieneś zastosować coś takiego do swojego zbioru danych. Nie wymieniaj i nie zapisuj, bo zniszczysz swoje dane! I przy okazji, nie powinieneś (prawie) nigdy usuwać wartości odstających ze swoich danych:

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
}

Aby zobaczyć to w akcji:

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

I jeszcze raz, nigdy nie powinieneś tego robić samodzielnie, wartości odstające po prostu powinny być! =)

EDYCJA: dodałem na.rm = TRUEjako domyślny.

EDIT2: Usunięto quantilefunkcję, dodano indeksowanie, dzięki czemu funkcja jest szybsza! =)

wprowadź opis obrazu tutaj

aL3xa
źródło
Dzięki za pomoc! Myślę, że jeśli R jest w stanie wyprowadzić wartości odstające w wykresie pudełkowym, nie powinienem wykonywać tych obliczeń pośrednich. Jeśli chodzi o usuwanie wartości odstających, jest to tylko przydział.
Dan Q
3
OK, coś mi tu brakuje. Chcesz usunąć wartości odstające z danych, więc możesz je wykreślić za pomocą boxplot. To wykonalne i powinieneś wtedy zaznaczyć odpowiedź @ Prasad, ponieważ odpowiedziałeś na twoje pytanie. Jeśli chcesz wykluczyć wartości odstające za pomocą „reguły odstających” q +/- (1.5 * H), przeprowadź analizę, a następnie użyj tej funkcji. Swoją drogą, zrobiłem to od zera, bez Google, więc jest szansa, że ​​wymyśliłem koło z tą moją funkcją ...
aL3xa
10
Nie powinieneś zadawać pytań przydziału na stackoverflow!
hadley,
7
Czy to oznacza, że ​​nie powinniśmy też na to odpowiadać? =)
aL3xa
5
„wartości odstające mają po prostu być”? Niekoniecznie. Mogą wynikać z błędów pomiarowych i muszą być dokładnie sprawdzone. Kiedy wartość odstająca jest zbyt duża, może to oznaczać coś lub nie tak dużo. Dlatego (przynajmniej w biologii) mediana zwykle mówi więcej o populacji niż średnia.
Rodrigo,
133

Nikt nie opublikował najprostszej odpowiedzi:

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

Zobacz także: http://www.r-statistics.com/2011/01/how-to-label-all-the-outliers-in-a-boxplot/

J. Win.
źródło
4
Naprawdę eleganckie. Dzięki. Należy jednak zachować ostrożność, jeśli dystrybucja ma więcej niż jeden tryb, a wartości odstające są rzeczywiście tylko nieliczne i rozproszone.
KarthikS
Byłoby wspaniale, gdybyś mógł uzyskać ich indeks w zbiorze danych. Sposób wykonania będzie filtrowany na podstawie wartości danych. Jeśli wykres pudełkowy również wykonuje grupowanie, niekoniecznie ta sama wartość danych będzie odstająca w każdej grupie
Adam,
2
Należy również wspomnieć, że nie zmienia to zbioru danych. To tylko metoda filtrowania. Jeśli więc zamierzasz używać zbioru danych bez wartości odstających, przypisz go do zmiennej. np.result = x[!x %in% boxplot.stats(x)$out]
Victor Augusto
Posiadanie tylko jednej linii kodu niekoniecznie oznacza, że ​​jest to proste! Nie zawsze jest łatwo zrozumieć jednoliniowy kod, szczególnie dla początkujących i bez komentarzy.
PeyM87
29

Użyj outline = FALSEjako opcji podczas wykonywania wykresu pudełkowego (przeczytaj pomoc!).

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

wprowadź opis obrazu tutaj

Prasad Chalasani
źródło
4
rzeczywiście, spowoduje to usunięcie wartości odstających z samego wykresu pudełkowego, ale chcę usunąć wartości odstające z ramki danych.
Dan Q
2
Widzę, jak powiedział @Joshua, musisz spojrzeć na dane zwrócone przez funkcję boxplot (w szczególności elementy outi groupna liście).
Prasad Chalasani
16

Funkcja boxplot zwraca wartości użyte do wykreślenia (co jest następnie wykonywane przez 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

Celowo nie odpowiedziałem na konkretne pytanie, ponieważ uważam, że usuwanie „wartości odstających” jest statystycznym błędem w sztuce. Uważam za dopuszczalną praktykę, aby nie wykreślić ich na wykresie pudełkowym, ale usunięcie ich tylko dlatego, że przekraczają pewną liczbę odchyleń standardowych lub pewną liczbę szerokości między kwartylami jest systematycznym i nienaukowym manipulowaniem zapisem obserwacyjnym.

IRTFM
źródło
4
Cóż, omijanie pytania bez wiedzy, dlaczego zostało ono zadane, również nie jest dobrą praktyką. Tak, usuwanie „wartości odstających” z danych nie jest dobre, ale czasami do określonych zadań potrzebne są dane bez wartości odstających. W zadaniu statystycznym, które miałem ostatnio, musieliśmy wizualizować zbiór bez wartości odstających, aby określić najlepszy model regresji do wykorzystania w danych. Więc tam!
Alex Essilfie,
4
Nie uważam rady, którą otrzymałeś w związku z „określeniem najlepszego modelu regresji” za szczególnie przekonującą. Zamiast tego, gdybyś musiał usunąć wartości odstające w tym niejasno określonym celu, to myślę, że to raczej słabo odzwierciedla osoby, które doradzały, niż jest dowodem nieważności mojego stanowiska.
IRTFM,
Myślę, że to uzasadnione, kiedy wiesz, że usuwasz „hałas”. zwłaszcza w danych fizjologicznych.
roscoe1895
Tak. Jeśli masz uzasadnione powody, by sądzić, że oddzielny proces tworzy sygnał, jest to uzasadnienie usunięcia z danych.
IRTFM
9

Wyszukałem pakiety związane z usuwaniem wartości odstających i znalazłem ten pakiet (zaskakująco nazywany „wartościami odstającymi”!): Https://cran.r-project.org/web/packages/outliers/outliers.pdf
jeśli przejrzysz go, zobacz różne sposoby usuwania wartości odstających, a wśród nich znalazłem rm.outliernajwygodniejszy w użyciu i jak jest napisane w linku powyżej: „Jeśli wartość odstająca zostanie wykryta i potwierdzona przez testy statystyczne, ta funkcja może ją usunąć lub zastąpić średnią lub medianą z próby” a także tutaj jest część dotycząca użytkowania z tego samego źródła:
Użycie

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

Argumenty
x zbiór danych, najczęściej wektor. Jeśli argument jest ramką danych, to wartość odstająca jest usuwana z każdej kolumny przez sapply. To samo zachowanie jest stosowane przez zastosowanie, gdy podana jest macierz.
wypełnienie Jeśli ustawione na PRAWDA, zamiast wartości odstającej umieszczana jest mediana lub średnia. W przeciwnym razie wartości odstające są po prostu usuwane.
mediana Jeśli jest ustawiona na PRAWDA, w zastępowaniu wartości odstających używana jest mediana zamiast średniej. przeciwnie, jeśli ustawione na PRAWDA, daje przeciwną wartość (jeśli największa wartość ma maksymalną różnicę od średniej, daje najmniejszą i odwrotnie) "

Peyman
źródło
Wydaje się to świetne, ale jeśli masz kolumnę szeregów czasowych w ramce danych, zmienia to szereg czasowy.
PeyM87
7
x<-quantile(retentiondata$sum_dec_incr,c(0.01,0.99))
data_clean <- data[data$attribute >=x[1] & data$attribute<=x[2],]

Uważam, że jest to bardzo łatwe do usunięcia wartości odstających. W powyższym przykładzie po prostu wyodrębniam 2 percentyl do 98 percentyla wartości atrybutów.

Gaurav Khare
źródło
5

Nie:

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

wykonać to zadanie dość łatwo?

d8aninja
źródło
4

Dodając do sugestii @sefarkas i używając kwantyla jako odcięcia, można zbadać następującą opcję:

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

Spowoduje to usunięcie punktów poza 99. kwantylem. Należy uważać, tak jak mówiła aL3Xa o utrzymywaniu wartości odstających. Należy go usunąć tylko w celu uzyskania alternatywnego, konserwatywnego spojrzenia na dane.

KarthikS
źródło
czy to jest 0.91czy 0.99? jak w mydata$var < quantile(mydata$var, probs=c(.01, .91))[1])ormydata$var < quantile(mydata$var, probs=c(.01, .99))[1])
Komal Rathi
Jeśli masz konkretny powód, aby użyć 91. percentyla zamiast 99. percentyla, możesz go użyć. To tylko heurystyka
KarthikS
1

Jednym ze sposobów na to jest

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

lub

my.high.value <- which(my.data.frame$age > 200 | my.data.frame$age < 0) 
my.NEW.data.frame <- my.data.frame[-my.high.value, ]
Seyma Kalay
źródło
0

Wartości odstające są dość podobne do pików, więc detektor pików może być przydatny do identyfikowania wartości odstających. Opisana tutaj metoda ma całkiem dobre wyniki przy użyciu wyników z-score. Animacja na dole strony ilustruje metodę sygnalizacji wartości odstających lub wartości szczytowych.

Piki nie zawsze są takie same jak wartości odstające, ale często są podobne.

Oto przykład: ten zestaw danych jest odczytywany z czujnika za pośrednictwem komunikacji szeregowej. Sporadyczne błędy komunikacji szeregowej, błąd czujnika lub oba te czynniki prowadzą do powtarzających się, wyraźnie błędnych punktów danych. W tym punkcie nie ma wartości statystycznej. Prawdopodobnie nie są to wartości odstające, są to błędy. Detektor pików z-score był w stanie zasygnalizować fałszywe punkty danych i wygenerował czysty wynikowy zestaw danych:wprowadź opis obrazu tutaj

Marc Compere
źródło
-1

Spróbuj tego. Wprowadź zmienną do funkcji i zapisz o / p w zmiennej, która zawierałaby usunięte wartości odstające

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)
}
Adipta Biwas
źródło
Dodaj wyjaśnienie do swojej odpowiedzi. Zobacz Jak odpowiedzieć .
ejderuby