Verideki aykırılıklar uygun şekilde belirlenip üstesinden gelinmezse, özellikle regresyon modellerinde tahminleri bozabilir ve doğruluğu etkileyebilir.
Çünkü uydurulmuş tahmin ve öngörüleri belirgin bir biçimde değiştirebilir. Bunu, arabalar veri setini kullanarak gösterebilirim.
Aykırı değerler ile ne anlatılmak istendiğini daha iyi anlamak için, arabalar veri seti üzerinde yapılmış olan lineer regresyon modelini aykırı değerler dahil ve aykırılıklar dahil olmadan olmak üzere karşılaştıracağım. Etkiyi daha iyi ayırt edebilmek için ekstrem değerleri, orijinal arabalar veri setine kendim giriyorum. Sonrasında ise iki veri seti üzerinde tahminlerde bulunuyorum.
# Inject outliers into data.
cars1 <- cars[1:30, ] # original data
cars_outliers <- data.frame(speed=c(19,19,20,20,20), dist=c(190, 186, 210, 220, 218)) # introduce outliers.
cars2 <- rbind(cars1, cars_outliers) # data with outliers.
# Plot of data with outliers.
par(mfrow=c(1, 2))
plot(cars2$speed, cars2$dist, xlim=c(0, 28), ylim=c(0, 230), main="With Outliers", xlab="speed", ylab="dist", pch="*", col="red", cex=2)
abline(lm(dist ~ speed, data=cars2), col="blue", lwd=3, lty=2)
# Plot of original data without outliers. Note the change in slope (angle) of best fit line.
plot(cars1$speed, cars1$dist, xlim=c(0, 28), ylim=c(0, 230), main="Outliers removed \n A much better fit!", xlab="speed", ylab="dist", pch="*", col="red", cex=2)
abline(lm(dist ~ speed, data=cars1), col="blue", lwd=3, lty=2)
Orijinal verinin aykırılıklar dahil olarak ve olmadan çizilmiş grafikleri:
Aykırılıkların kaldırılması ile en iyi uydurma çizgisinin eğimi üzerindeki değişime dikkat ediniz. Eğer aykırılıkları modelden kaldırmamış olsaydık (soldaki grafik), yüksek eğimden dolayı tahminlerimiz yüksek değerler için abartılmış olurdu (yüksek hata).
Aykırılıkların Belirlenmesi
Tek Değişkenli Yaklaşım
Aykırılıklar, verilmiş bir sürekli değişken için 1.5*IQR dışında kalan gözlemlerdir. IQR, (kartiller arası aralık) %75 ve %25 kartiller (dördünler) arasındaki farkı verir. Aşağıdaki kutu grafikte, alt ve üst limitler dışında kalan noktaları inceleyelim.
outlier_values <- boxplot.stats(inputData$pressure_height)$out # outlier values.
boxplot(inputData$pressure_height, main="Pressure Height", boxwex=0.1)
mtext(paste("Outliers: ", paste(outlier_values, collapse=", ")), cex=0.6)
İki Değişkenli Yaklaşım
Kategorik X değerleri için, X ve Y değerlerini kutu grafiğinde görsel hale getirelim.
url <- "http://rstatistics.net/wp-content/uploads/2015/09/ozone.csv"
ozone <- read.csv(url)
# For categorical variable
boxplot(ozone_reading ~ Month, data=ozone, main="Ozone reading across months") # clear pattern is noticeable.
boxplot(ozone_reading ~ Day_of_week, data=ozone, main="Ozone reading for days of week") # this may not be significant, as day of week variable is a subset of the month var.
Kutu-grafiği:
Çıkarım nedir? Kutuların seviyelerindeki değişim, ayın ozon değerleri üzerinde etkisi var iken haftanın gününün etkisi olmadığını gösteriyor. İlgili kategorik düzeydeki aykırı değerler, kutu grafiğinin bıyıklarının dışında noktalar olarak görünür.
# For continuous variable (convert to categorical if needed.)
boxplot(ozone_reading ~ pressure_height, data=ozone, main="Boxplot for Pressure height (continuos var) vs Ozone")
boxplot(ozone_reading ~ cut(pressure_height, pretty(inputData$pressure_height)), data=ozone, main="Boxplot for Pressure height (categorial) vs Ozone", cex.axis=0.5)
Kutu grafiğinde birkaç aykırı değer ve ozon değerlerinin basınç yüksekliği ile nasıl arttığını görebilirsiniz. Bu açıktır.
Cook’un mesafesi, belirli bir regresyon modeline göre hesaplanan bir ölçüdür ve bu nedenle yalnızca modele dahil edilen X değişkenlerinden etkilenir. Peki Cook mesafesi ne anlama geliyor? Her veri noktasının (satır) öngörülen sonuç üzerindeki etkisini hesaplar. Her gözlem i’ye denk gelen Cook mesafesi, gözlem i olan ve olmayan tüm gözlemler için Ŷ (uydurulmuş Y) ‘deki değişikliği ölçer.
mod <- lm(ozone_reading ~ ., data=ozone)
cooksd <- cooks.distance(mod)
Genelde Cook mesafesi ortalamanın 4 katından daha fazla olan gözlemler, etkisel olarak sınıflandırılabilir. Bu katı bir sınır değildir.
plot(cooksd, pch="*", cex=2, main="Influential Obs by Cooks distance") # plot cook's distance
abline(h = 4*mean(cooksd, na.rm=T), col="red") # add cutoff line
text(x=1:length(cooksd)+1, y=cooksd, labels=ifelse(cooksd>4*mean(cooksd, na.rm=T),names(cooksd),""), col="red") # add labels
Cook mesafesine göre etkili gözlemler:
Şimdi orijinal verilerden etkili kayıtları bulalım. Her etkili satırı birer birer çıkarır ve incelerseniz (çıktının altından), bu satırın neden etkisel olduğunu anlayabilirsiniz. Modelde yer alan X değişkenlerinden birinin uç değerlere sahip olması muhtemeldir.
influential 4*mean(cooksd, na.rm=T))]) # influential row numbers
head(ozone[influential, ]) # influential observations.
#> Month Day_of_month Day_of_week ozone_reading pressure_height Wind_speed Humidity
#> 19 1 19 1 4.07 5680 5 73
#> 23 1 23 5 4.90 5700 5 59
#> 58 2 27 5 22.89 5740 3 47
#> 133 5 12 3 33.04 5880 3 80
#> 135 5 14 5 31.15 5850 4 76
#> 149 5 28 5 4.82 5750 3 76
#> Temperature_Sandburg Temperature_ElMonte Inversion_base_height Pressure_gradient
#> 19 52 56.48 393 -68
#> 23 69 51.08 3044 18
#> 58 53 58.82 885 -4
#> 133 80 73.04 436 0
#> 135 78 71.24 1181 50
#> 149 65 51.08 3644 86
#> Inversion_temperature Visibility
#> 19 69.80 10
#> 23 52.88 150
#> 58 67.10 80
#> 133 86.36 40
#> 135 79.88 17
#> 149 59.36 70
Bu satırların neden etkisel gözlemler olarak etiketlenebileceğini öğrenmek için yukarıdaki çıktıdan ilk altı satırı inceleyelim.
-Satır 58, 133, 135’te çok yüksek ozon değerleri vardır.
-Satır 23, 135 ve 149 çok yüksek Inversion_base_height değerine sahiptir.
-Satır 19’da çok düşük basınç gradyanı vardır.
Car paketindeki outlierTest fonksiyonu, verilen modele bağlı olarak en uç değerleri verir.
car::outlierTest(mod)
#> No Studentized residuals with Bonferonni p Largest |rstudent|:
#> rstudent unadjusted p-value Bonferonni p
#> 243 3.045756 0.0026525 0.53845
Bu çıktı, satır 243’teki gözlemin en ekstrem nokta olduğunu göstermektedir.
Aykırı değer paketi, aykırı değerleri sistematik olarak ayıklamak için bir dizi kullanışlı fonksiyon sağlar. Bunlardan özellikle outlier ()
ve score ()
işlevleri kullanışlıdır.
Outliers fonksiyonu, ortalama değerden (mean) en uç gözlemi bulur. Eğer komutta opposite=TRUE kullanırsanız, gözlemi diğer taraftan alır.
set.seed(1234)
y=rnorm(100)
outlier(y)
#> [1] 2.548991
outlier(y,opposite=TRUE)
#> [1] -2.345698
dim(y) <- c(20,5) # convert it to a matrix
outlier(y)
#> [1] 2.415835 1.102298 1.647817 2.548991 2.121117
outlier(y,opposite=TRUE)
#> [1] -2.345698 -2.180040 -1.806031 -1.390701 -1.372302
Scores() fonksiyonunun iki kullanımı vardır.
-Normalleştirilmiş skorları, “z”, “t”, “chisq” ve benzerlerini temel alarak hesaplar.
-Belirli bir yüzdeye dayalı olarak verilen bir yüzdelik değerin ötesinde olan gözlemleri bulur.
set.seed(1234)
x = rnorm(10)
scores(x) # z-scores => (x-mean)/sd
scores(x, type="chisq") # chi-sq scores => (x - mean(x))^2/var(x)
#> [1] 0.68458034 0.44007451 2.17210689 3.88421971 0.66539631 . . .
scores(x, type="t") # t scores
scores(x, type="chisq", prob=0.9) # beyond 90th %ile based on chi-sq
#> [1] FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
scores(x, type="chisq", prob=0.95) # beyond 95th %ile
scores(x, type="z", prob=0.95) # beyond 95th %ile based on z-scores
scores(x, type="t", prob=0.95) # beyond 95th %ile based on t-scores
Aykırı değerler belirlendikten sonra, aşağıdaki yaklaşımlardan birini kullanarak düzeltebilirsiniz.
Yakıştırma
Ortalama / medyan / modu ile yakıştırma (eksik verilerin değerlerinin belirlenmesi). Bu yöntem, eksik değerlerin üzerine işlemler ile ilgili tartışmada ayrıntılı olarak ele alınmıştır. DataScience+’da ele aldığımız bir diğer sağlam yöntem, zincirleme denklemlerin çok değişkenli yakıştırmasıdır.
Sınırlama
.5 * IQR sınırlarının dışında kalan eksik değerleri, alt sınırın dışındaki gözlemleri 5. (beşinci) yüzdelik değeri ile ve üst sınırın üzerinde bulunan gözlemleri 95. yüzdelik değeri ile değiştirerek kapatabiliriz. Aşağıda bunu başaran bir örnek kod bulunmaktadır.
x <- ozone$pressure_height
qnt <- quantile(x, probs=c(.25, .75), na.rm = T)
caps <- quantile(x, probs=c(.05, .95), na.rm = T)
H <- 1.5 * IQR(x, na.rm = T)
x[x < (qnt[1] - H)] (qnt[2] + H)] <- caps[2]
Tahmin
Yine başka bir yaklaşımda, aykırı değerler, eksik değerleri NA
ile değiştirilebilir ve daha sonra bunları bir cevap değişkeni olarak düşünerek tahmin edilebilir. Zaten eksik değerlerin nasıl tahmin edileceğini tartışmıştık.
Kaynak: Outlier detection and treatment with R | R-bloggers (r-bloggers.com)