Statisztika egyszerűen

Mágikus jelek nélkül...

Kívülállók… - Adatsorok kieső értékeinek vizsgálata R-ben

2021. május 07. 08:00 - glantos70

Six Sigma in R

Ezzel a témával is foglalkoztam már (Kancsal tengerész nem tud célozni! – Kieső értékek vizsgálata), de ugye itt most az a távlati cél, hogy a Six Sigma módszertanban alkalmazott leggyakoribb eszközöket hogyan tudjuk használni R-ben. Ezt most be is fogom mutatni, de azért lesznek újdonságok is a korábbiakhoz képest.

Először is az utóbbi időben felvett szokásom szerint létrehoztam egy mintát, ez esetben azzal a kitétellel, hogy az adatsornak tartalmaznia kell kieső értékeket is. Ezt úgy értem el, hogy nem egy, hanem két mintát hoztam létre véletlen számokból. Egy 15 eleműt (minta1) és egy 3 eleműt (minta2), majd ezeket összekombináltam és megkevertem.

#A kieső értékeket tartalmazó minta előállítása
minta1 <- rnorm(15, mean = 0, sd = 1)
minta1

minta2 <- rnorm(3, mean = 10, sd = 0.2)
minta2

#A két minta kombinálása egy vektorba
minta <- c(minta1, minta2)
minta

#A mintaelemek sorrendjének megkeverése
minta <- sample(minta)
minta

Így egy olyan 18 elemből álló mintát kaptam, amelynek nyilvánvalóan van 3 kieső eleme, ahogyan az a következő diagramból is kitűnik.

 

A diagramok elkészítésekor nem alkalmaztam a korábbiakhoz képest nagyon új dolgokat, de egy-két apróságot érdemes megemlíteni.

#ggplot2 és gridExtra csomagok betöltése
library(ggplot2)
library(gridExtra)

#pontdiagram
xtg <- c(seq(1, 18, 1))            #x-tengely beosztása
plot1 <- ggplot() +
  geom_point(aes(x = xtg, y = minta)) +
  labs(title = "A minta pontdiagramja")

#A minta dobozdiagramja
plot2 <- ggplot() +
  geom_boxplot(aes(y = minta)) +
  labs(title = "Dobozdiagram (boxplot)")

#A két diagram elhelyezése egymás mellett
grid.arrange(plot1, plot2, ncol = 2)

A pont diagram esetében a pontokat sorrendben szerettem volna ábrázolni. Sajnos a ‘geom_point()’ függvény “igényli” a független változó jelenlétét, ezért létre kellett hoznom egy ‘xtg’ nevű változót, amely 1 és 18 közötti egész számokat tartalmaz szépen sorban. A ‘c()’ és a ‘seq()’ függvények működését már korábban ismertettem (Mi is az a hipotézis vizsgálat?). Ezután már csak a két diagramot kellett elkészítenem. A pontdiagramot a ‘geom_point()’, a dobozdiagramot pedig a ‘geom_boxplot()’ függvény alkalmazásával tudtam elkészíteni. Ezek esetében az x és az y értékeit az ‘aes()’ függvénnyel tudtam megadni, mert ezek meglepő módon esztétikai jellemzőkként vannak kezelve a ggplot2-ben. A többi tulajdonképpen ugyanaz, mint korábban.

A jobb oldali dobozdiagram szépen kiemeli a kieső értékeket. Azt, hogy ezt mi alapján teszi, a cikk elején hivatkozott előző bejegyzésben már elmagyaráztam. Viszont az R megadja a lehetőséget arra is, hogy pontosan megtudjuk, melyik értékek a kiesők. A ‘geom_boxplot()’ diagramhoz hozzátartozik egy több különböző elemből álló kis “adatbázis” is, amelynek az értékeit egy függvény segítségével praktikusan le is tudjuk kérdezni.

#boxplot kiesőinek kiolvasása
outl <- boxplot.stats(x = minta, coef = 1)$out
outl

A fontos, az az, hogy a ‘boxplot.stats()’ függvény kimenete ez a kis adattábla, amelynek az egyes mezőire ugyanúgy tudunk hivatkozni, mint egy bármilyen más adattáblára, vagyis az oszlop vagy mező nevét a ‘$’ jel után írva. Ekkor a függvény kiírja azokat az értékeket, amelyeket kiesőkként kezel.

Amennyiben az adatsorunk valamilyen paraméteres eloszlást követ, vagyis rá tudunk húzni egy bizonyos paraméterekkel meghívott sűrűségfüggvényt az adatainkra, akkor megpróbálhatjuk a quantilis módszert, azaz a sűrűségfüggvény alapján kiszámoljuk a 95%-os megbízhatósági tartományt és megnézzük, hogy az adatsor mely értékei kerültek ezen kívül. Ennek a módszernek én abban látom a hátrányát, hogy ha kieső értékek vannak egy adatsorban, akkor eleve nehézségekbe fog ütközni, hogy egy paraméteres sűrűségfüggvényt ráillesszünk az adatokra. Ha netán véletlenül ez mégis sikerülne, akkor viszont miért mutatná ki a quantilis módszer a kieső értékeket? Szóval szerintem ez nem igazán működik.

Szokták még alkalmazni az úgynevezett Hampel-szűrőt, amely a mediánt alkalmazza az átlag helyett, így kiküszöböli az átlag kieső értékek általi torzulását. A módszer egyáltalán nem bonyolult.

  • Először is kiszámítjuk az adatsor mediánját - Me,
  • majd kiszámoljuk az adatsor összes pontjának mediántól mért abszolút távolságát - |Pi – Me|,
  • megkeressük az előző pontban kiszámolt távolságok mediánját - Mei,
  • végül kiválasztjuk azokat a pontokat, amelyek távolsága nagyobb, mint (4,5*Mei) az adatsor mediánjától (Me)

A |Pi – Me|, azaz az adathalmaz pontjainak abszolút távolsága a mediántól az úgynevezett MAD (Median Absolute Deviation), amely nem egyezik meg a már korábban említett másik MAD-del, amely a Mean Absolute Deviation rövidítése (Variancia négyzetgyöke vs. eltérések abszolút értéke). De honnan jön a 4,5? Miért pont 4,5-tel kell megszorozni a minták távolságainak mediánját ahhoz, hogy megkapjuk a kieső értékek határát? A válasz egy becslés, mely szerint egy adatsor szórása megegyezik a MAD körülbelül másfélszeresével.

A medián alkalmazása arra utal, hogy ez egy nemparaméteres módszer, azaz az eredmény nem függ az adathalmaz eloszlásától.

R-ben ezt egyrészt egyszerűen ki lehet számítani a következő kód segítségével, illetve a ‘pracma’ nevű csomag tartalmaz egy ‘hampel()’ függvényt, de ezt elsősorban idősorok elemzésekor tudjuk alkalmazni, ott ezt a szűrőt előszeretettel alkalmazzák. Egy ilyen egyszerűbb esetben viszont nem biztos, hogy működni fog a bemenő adatok formátumának eltérései miatt. De nézzük a kódot:

#Kieső értékek meghatározása Hampel-szűrő segítségével

#A minta mediánjának kiszámítása
mintaMedian <- median(minta)

#A minta elemeinek távolsága a minta mediánjától (ebből egy vektor lesz!)
mintaTav <- abs(minta - mintaMedian)

#A mintatávolságok mediánja
mintaTavMedian <- median(mintaTav)

#A kieső értékek kiválasztása (mintaTav > 4,5 * mintaTavMedian)
Kiesok <- minta[mintaTav > 4.5 * mintaTavMedian]

Ebben a kódban az tetszik a legjobban, hogy milyen egyszerűen kiszűrhetők a kieső értékek a mintából. Ezt az teszi lehetővé, hogy noha a minták mediántól mért távolságának adatai teljesen függetlenek a minta adataitól (nincs semmilyen azonosító, ami összekötné őket), de mivel nem változtattam meg ezek sorrendjét, ezért biztosra vehetem, hogy a minták és ezek távolságai a mediántól megfelelő sorrendben vannak.

Az eredményként kapott három adat tökéletesen megfelel a dobozdiagram által már kimutatott kieső értékeknek.

A cikk elején hivatkozott előző bejegyzésemben már említettem, hogy léteznek hipotézis vizsgálatok is a kieső értékek vizsgálatára, mint amilyen a Grubb’s teszt vagy a Dixon’s teszt. Ezek elterjedten alkalmazott tesztek, így természetesen az R-ben is megtalálhatók. A kieső értékek detektálására létezik egy külön csomag az ‘outliers’. Ebben találhatók a ‘grubbs.test()’ és a dixon.test()’ függvények, amelyekkel a fent említett teszteket el tudjuk végezni. Ezek részletes leírását és használatának módját a cikk elején hivatkozott bejegyzésben megtalálod.

Érdekes módon a Grubb’s teszt eredménye az lett, hogy a minta adatsorban NINCSENEK kieső értékek! A p-érték 0,1998, ami nagyobb, mint 0,05, vagyis a nullhipotézist el kell fogadnunk! Erre minimum annyit mondanék meghökkenve, hogy “nocsak”, hiszen fentebb ugyanebben az adatsorban hármat is találtam a korábban említett módszerekkel! Sajnos a szakirodalom is megerősíti, hogy mind a Grubb’s teszt, mind pedig a Dixon’s teszt eléggé konzervatív a kieső értékek kijelzésében.

És akkor most jön a legjobb rész!

A tesztet úgy hívják, hogy “általánosított extrém studentált eltérő érték” teszt (generalized Extreme Studentized Deviate test, vagy generalized ESD test), de profán módon csak úgy egyszerűen Rosner-tesztnek is nevezik. Ezt a tesztet még nem ismertem, de mind közül ez lett a kedvencem. Egyrészt, mert végre egy outlier teszt, ami nemcsak egy kieső értéket képes detektálni, hanem akár az összeset is, másrészt mert az algoritmusa nagyon egyszerű és ötletes, harmadrészt pedig mert a megvalósítása R-ben nagyon egyszerű és kényelmes. A korábban említett Grubb’s és Dixon’s tesztek esetében a nullhipotézis az volt, hogy az adathalmazban nincs kieső érték, az ellenhipotézis pedig az, hogy az adatsorban legalább egy kieső érték van. A Rosner-teszt esetében a nullhipotézis és az ellenhipotézis a következő.

  • Ho: A vizsgált ‘n’ elemű adathalmazban nincsenek kieső értékek
  • H1: A vizsgált ‘n’ elemű adathalmazban ‘r’ darab kieső érték van.

A módszer ravaszsága abban van, hogy ez egy iteratív módszer, amelynek külön pikantériája, hogy nem kell pontosan tudnunk előre a kieső értékek számát. Ha körülbelül sejtjük, hogy hány kieső érték lehet a vizsgált adatsorban, akkor elég egy ennél nagyobb számot megadni a teszt megkezdésekor. Ez azt jelenti, hogy mondjuk az általam vizsgálat adatsorban azt sejtem, hogy 3 kieső érték lehet (ez lesz ‘r’), akkor a teszt megkezdésekor megadom, hogy szerintem a kieső értékek száma 4 vagy 5, esetleg 6 (ez lesz a ‘k’). A teszt végrehajtása után az eredmény meg fogja mutatni, hogy pontosan hány kieső érték van az adatsorban. Azt viszont legalább sejtenünk kell, hogy a kieső értékek kisebbek vagy nagyobbak, mint az adatsor többi része.

  • A teszt végrehajtásakor először is nagyság szerint sorba rendezzük a vizsgált adatsor elemeit. A kiválasztott ‘k’ darab értékre kiszámítjuk az

           próbastatisztikát, ahol x̅ a vizsgált adathalmaz átlaga, s pedig a szórása.

  • Ezután az ‘k’ adat közül eltávolítjuk azt az adatot, amelynél Ri értéke a legnagyobb, majd újraszámoljuk az adatsor átlagát és szórását az előbb eltávolított elem nélkül.
  • Ezután újra kiszámoljuk Ri értékeit a fenti képlet segítségével, most már k-1 értékre.
  • Ezután újra eltávolítjuk azt az elemet, amelynél az Ri értéke a legnagyobb, és így tovább mindaddig, amíg i értéke 1 nem lesz. Természetesen minden körben eltároljuk Ri maximális értékeit.
  • Ezután jön a próba határértékének kiszámítása, amely egy fokkal bonyolultabb képlet segítségével történik.

          A ‘tp,ν’ értéke a df = ν szabadsági fokú student-féle t-eloszlás (A sörfőző, aki forradalmasította a statisztikát)            p valószínűségéhez tartozó érték, ahol

           ahol α 95%-os megbízhatósági szint esetén 0,05, 99%-os esetén 0,01, és így tovább.

A lényeg, hogy a mintában annyi kieső érték van, amelyik ‘i’ esetében az Ri próbastatisztika értéke nagyobb, mint a λi értéke. Természetesen megértem, hogy a fenti leírás nehezen követhető, ezért elkészítettem ezt a példát táblázatkezelőben is a jobb láthatóság kedvéért, ezt a cikk végén le tudod tölteni az R szkriptekkel együtt.

A táblázat bal oldalán látható az eredeti adatsor. Ezt először is nagyság szerint csökkenő sorrendbe rendeztem, majd kiszámítottam az adatsorok átlagait és szórásait. A sorba rendezés miatt mindig a legfelső elem fog kiesni, ezért tudom a szükséges átlagokat és szórásokat ezen a módon kiszámítani.

Ezután kiszámítottam az Ri próbastatisztikákat (az első táblázatot addig elrejtettem, hogy látszódjanak a sorok számai). Itt már jól látható, hogy a sorbarendezés miatt mindig a legelső Ri érték a legmagasabb, ezeket meg is vastagítottam. Arra kellett vigyázni, hogy mindig a megfelelő átlagokat és szórásokat használjam.

Most jön a feketeleves, a Lambda határértékek kiszámítása.

  • Először p értékét számítottam ki a fenti képlet segítségével. Itt mindenképpen kiemelném, hogy α értékének 0,5-öt kell használni, n értéke ez esetben 18, i értékét pedig a Ssz oszlopban lévő szám adja meg.
  • Ha p megvan, akkor a ‘t.inverz()’ függvény segítségével ki lehet számolni, hogy milyen x - érték tartozik a nu = n - i – 1 szabadsági fokú student-eloszlás p valószínűségéhez.
  • Ezután ezt egyszerűen négyzetre emeltem, mert ez kell majd a Lambda nevezőjébe.
  • Ezután jött a számláló és a nevező kiszámítása, majd ezek hányadosa megadja Lambda értékét.

Végül jön a döntés, hogy hány kieső érték van az adatsorban. Ri értéke a harmadik sorban nagyobb, mint a Lambda határérték, így az eredmény az, hogy három kieső érték van az adatsorban.

A teszt hátránya az, hogy az adatsornak közelítőleg normál eloszlásúnak kell lennie a próbastatisztika standardizáló képlete miatt, ezért a Rosner-teszt alkalmazása előtt ez esetben érdemes ellenőrizni az adatok normalitását (Ha nem normál eloszlás, akkor micsoda? – adatsor eloszlásának azonosítása R-ben (Six Sigma in R)). Összességében elmondható, hogy a Rosner-teszt tulajdonképpen egymás után végrehajtott Grubb’s-tesztek sorozata egy kicsit fűszerezve, de a képletek bonyolultsága ellenére nem vészes az alkalmazása. Mondjuk azt ne kérdezd meg, hogy miért működik…

Most nézzük meg, hogy néz ez ki R-ben. Az ‘EnvStats’ csomag kezd egyre inkább a kedvencem lenni, mert a ‘rosnerTest()’ függvény is ebben a csomagban van benne. Szerencsére ennek az alkalmazása is egészen egyszerű, összesen négy potenciálisan alkalmazható paramétere van.

x – A vizsgálandó adatsor

k – a valószínű kieső értékek száma, amit én fentebb is k-val jelöltem. Az a fontos, hogy ez nagyobb legyen, mint ahány kieső értéket sejtünk az adatsorban.

alpha – A választott megbízhatósági szint, lehet 0,05 vagy 0,01 vagy akár más is…

warn – Ez egy logikai paraméter, ha TRUE az értéke (ez az alappbeállítás), akkor az eredmény nyomtatásakor a függvény figyelmeztetést ad, ha az elsőfajú hiba (Type I error) túl magas.

Az eredmény a fenti részletes magyarázatok függvényében jól értelmezhető. Ri értékei láthatók a riport közepén és az alul lévő táblázatban is. A ‘Mean.i’ és az ‘SD.i’ oszlopokban láthatóak a mintaátlagok és a szórások, a ‘Value’ oszlopban a minta értékei, az ‘Obs.Num’ oszlop adja meg, hogy az értékek eredetileg hányadikak voltak az adatsorban. Az ‘R.i+1’ és a ‘lambda.i+1’ oszlopokban vannak az Ri és a Lambda_i értékek, az ‘Outlier’ oszlop pedig a kieső értékek azonosítását tartalmazza IGAZ vagy HAMIS jelöléssel, ahol természetesen a TRUE-val jeölt értékek a kiesők.

Összegzés:

Bár az elején nem számítottam rá, ismét sikerült újat tanulnom. A Hampel-szűrő és a Rosner-teszt is tetszik, jól kiegészítik az eddigi ismereteimet. Az ‘EnvStats’ csomagnak is egyre több hasznos függvényét ismerem meg, úgy látom, még fogunk vele találkozni a jövőben is. Végezetül külön szeretném kiemelni, hogy a kieső értékek azonosítása esetében ezek csak az első lépések, léteznek már olyan gépi tanulási algoritmusok is, amelyek a fentieknél bonyolultabb problémák esetén is alkalmazhatók, mint például a DbScan (Density Based Spatial Clustering of Applications with Noise) vagy az Isolation Forests, de ezekkel majd talán később fogok foglalkozni.

Az excel táblázatot és az R szkripteket innen tudod letölteni.

Források:

Package ‘outliers’
https://cran.r-project.org/web/packages/outliers/outliers.pdf

Manoj K, Senthamarai Kannan K: Comparison of methods for detecting outliers, International Journal of Scientific & Engineering Research, Volume 4, Issue 9, September-2013

What is a “Hampel Filter” and how does it work? - Stackexchange
https://dsp.stackexchange.com/questions/26552/what-is-a-hampel-filter-and-how-does-it-work

Peter J. Rousseeuw: Robust Estimation and Identifíing Outliers,
https://wis.kuleuven.be/stat/robust/papers/publications-1990/rousseeuw-robustestimation-handbookengineersscient.pdf

Engineering Statistics Handbook: Generalized ESD Test for Outliers
https://www.itl.nist.gov/div898/handbook/eda/section3/eda35h3.htm

rosnerTest function - RDocumentation
https://www.rdocumentation.org/packages/EnvStats/versions/2.3.1/topics/rosnerTest

2 komment

A bejegyzés trackback címe:

https://statisztikaegyszeruen.blog.hu/api/trackback/id/tr4616432542

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

vmiki a troll 2021.05.10. 08:48:56

Sajnalom, hogy blog ennyire megvaltozott, es mostbar inkabb egy R tanfolyam, mar csak a kodra koncentralva, nem statisztika egyszeruen, ahol rengeteget tanultam korabban. Koszonom az eddigieket.

glantos70 2021.05.10. 08:49:32

@vmiki a troll: Rendben, lelazulok egy kicsit... :-)
süti beállítások módosítása