Veri madenciliği için faktör seviyelerini birleştiren R paketi?


10

Bir faktördeki tüm düzeylerin oranı bir eşiğin altında olan bir faktörün seviyelerini birleştirecek olan R'de bir paket / fonksiyon boyunca herkesin çalışıp çalışmadığını merak ediyor musunuz? Özellikle, veri hazırlamanın ilk adımlarından biri, toplamın en az% 2'sini oluşturmayan seyrek faktör düzeylerini ('Diğer' adı verilen bir seviyeye) birlikte çöktürmektir. Bu denetimsiz olarak yapılır ve hedef pazarlamadaki bazı faaliyetleri modellemek olduğunda yapılır (bu çok küçük olayların son derece önemli olabileceği sahtekarlık tespiti değil). Bazı eşik oranları karşılanana kadar seviyeleri daraltacak bir işlev arıyorum.

GÜNCELLEME:

Bu harika öneriler sayesinde kolayca bir fonksiyon yazdım. Seviyeleri <en düşük oranla daraltmanın mümkün olduğunu fark ettim ve yine de en düşük oranın en düşük seviyeye eklenmesini gerektiren en düşük seviyenin <minimum olması gerekir. Muhtemelen daha verimli olabilir ama işe yarıyor gibi görünüyor. Bir sonraki geliştirme, daralma mantığını yeni verilere (bir doğrulama seti veya gelecekteki veriler) uygulamak için "kuralların" nasıl yakalanacağını bulmak olacaktır.

collapseFactors<- function(tableName,minPercent=5,fillIn ="RECODED" )
{
    for (i in 1:ncol(tableName))
        {   

            if(is.factor(tableName[,i]) == TRUE) #process just factors
            {


                sortedTable<-sort(prop.table(table(tableName[,i])))
                numberToCollapse<-length(sortedTable[sortedTable<(minPercent/100)])

                if (sum(sortedTable[1:numberToCollapse])<(minPercent/100))
                    {
                        numberToCollapse=numberToCollapse+1 #add next level if < minPercent
                    }

                if(numberToCollapse>1) #if not >1 then nothing to collapse
                {
                    lf <- names(sortedTable[1:numberToCollapse])
                    levels(tableName[,i])[levels(tableName[,i]) %in% lf] <- fillIn
                }
            }#end if a factor


        }#end for loop

    return(tableName)

}#end function

Yanıtlar:


11

Görünüşe göre bu sadece faktörün "yeniden ilişkilendirilmesi" meselesidir; kısmi toplamları hesaplamaya veya orijinal vektörün bir kopyasını oluşturmaya gerek yoktur. Örneğin,

set.seed(101)
a <- factor(LETTERS[sample(5, 150, replace=TRUE, 
                           prob=c(.1, .15, rep(.75/3,3)))])
p <- 1/5
lf <- names(which(prop.table(table(a)) < p))
levels(a)[levels(a) %in% lf] <- "Other"

Burada, orijinal faktör seviyeleri aşağıdaki gibi dağıtılır:

 A  B  C  D  E 
18 23 35 36 38 

ve sonra olur

Other     C     D     E 
   41    35    36    38 

Uygun bir şekilde bir fonksiyona sarılabilir. Yeniden şekillendirme paketinde bir combine_factor()işlev var , bu yüzden de yararlı olabilir sanırım.

Ayrıca, veri madenciliği ile ilgileniyor gibi göründüğünüz gibi, caret paketine bir göz atabilirsiniz . Göz ön nearZeroVar()değerlerin çok dengesiz dağılımıyla işaretleyicileri işaretlemesine izin veren işlevler de dahil olmak üzere veri önişleme için birçok yararlı özelliğe sahiptir (Bkz. Skeç, örnek veriler, ön işleme işlevleri, görselleştirmeler ve diğer işlevler , s. kullanım).


@CHI Teşekkürler. Düzeltme paketini inceledim ve meta parametrelerini ayarlamak için kullandım. çok kullanışlı!.
B_Miner

@chl +1, iyi olan. Ben sadece benim fonksiyon yazdım çünkü kod [% lf% (a)% seviyeleri] <- "Diğer" çalışmıyor, bu yüzden faktör seviyesi değişikliği karmaşık bir ilişki olduğunu kabul. Her zamanki gibi, R karmaşık değil, ben :) ortaya çıktı
mpiktas

@mpiktas Thx. Vektör seviyesinde örneğin, ile çalışabilirsiniz a[as.character(a) %in% lf] <- lf[1]; a <- factor(droplevels(a), labels=c("Other",LETTERS[3:5])).
chl

+1. a [% lf içindeki% (a)% seviyeleri] <- "Diğer" bir ton kod satırını kaydeder. Akıllı ve verimli!
Christopher Aden

Ancak bir [a == "a"] <- "Diğer" ifadesinin işe yaramayacağını unutmayın. Özellikle bir [a == "a"] tamamen geçerli olduğundan.
mpiktas

5

Christopher cevabı ile ilgili tek sorun, faktörün orijinal sırasını karıştıracağıdır. İşte benim düzeltmem:

 Merge.factors <- function(x, p) {
     t <- table(x)
     levt <- cbind(names(t), names(t)) 
     levt[t/sum(t)<p, 2] <- "Other"
     change.levels(x, levt)
 }

change.levelsaşağıdaki işlev nerede . Bir süre önce yazdım, bu yüzden ne yapmanın daha iyi yolları olabileceğinden şüpheleniyorum.

 change.levels <- function(f, levt) {
     ##Change the the names of the factor f levels from
     ##substitution table levt.
     ## In the first column there are the original levels, in
     ## the second column -- the substitutes
     lv <- levels(f)
     if(sum(sort(lv) != sort(levt[, 1]))>0)
     stop ("The names from substitution table does not match given level names")
     res <- rep(NA, length(f))

     for(i in lv) {
          res[f==i] <- as.character(levt[levt[, 1]==i, 2])
     }
     factor(res)
}

4

Bu hedefe ulaşmak için hızlı bir fonksiyon yazdım. Ben acemi bir R kullanıcısıyım, bu yüzden büyük tablolarla yavaş olabilir.

Merge.factors <- function(x, p) { 
    #Combines factor levels in x that are less than a specified proportion, p.
    t <- table(x)
    y <- subset(t, prop.table(t) < p)
    z <- subset(t, prop.table(t) >= p)
    other <- rep("Other", sum(y))
    new.table <- c(z, table(other))
    new.x <- as.factor(rep(names(new.table), new.table))
    return(new.x)
}

Uygulamadaki bir örneği olarak:

> a <- rep("a", 100)
> b <- rep("b", 1000)
> c <- rep("c", 1000)
> d <- rep("d", 1000)
> e <- rep("e", 400)
> f <- rep("f", 100)
> x <- factor(c(a, b, c, d, e, f))
> summary(x)
   a    b    c    d    e    f 
 100 1000 1000 1000  400  100 
> prop.table(table(x))
x
         a          b          c          d          e          f 
0.02777778 0.27777778 0.27777778 0.27777778 0.11111111 0.02777778 
> 
> w <- Merge.factors(x, .05)
> summary(w)
    b     c     d     e Other 
 1000  1000  1000   400   200 
> class(w)
[1] "factor"

Gözlem için teşekkürler, John. Bunu bir faktör haline getirmek için biraz değiştirdim. Yaptığım tek şey orijinal vektörü tablodan yeniden yapmaktı, bu yüzden bu adımı atlamanın bir yolu varsa, bu daha hızlı olacaktır.
Christopher Aden

Yanıt veren herkese teşekkürler. R'm zayıf ama bunu çok az kod satırıyla yapabilme yeteneği ne kadar güçlü olduğunun kanıtı ve beni öğrenmek istememe neden oluyor.
B_Miner
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.