用于组合因子级别以进行数据挖掘的R包?


10

想知道是否有人在R中的某个包/函数上运行过,它将组合某个因子的水平,而该水平在一个因子中的所有水平的比例小于某个阈值?具体来说,我进行数据准备的第一步之一就是将稀疏的因子水平合在一起(称为“其他”因子),这些因子至少不构成总数的2%。这是在无监督的情况下完成的,并且当目标是为营销中的某些活动建模时(而不是欺诈检测,因为那些很小的事件可能非常重要),可以执行此操作。我正在寻找一个可以折叠水平直到达到某个阈值比例的函数。

更新:

由于这些出色的建议,我很容易地编写了一个函数。我确实意识到,虽然有可能使比例<最小值的水平崩溃,而仍然使重新编码的水平<最小值,但需要添加比例>最小值的最低水平。可能会更有效,但它似乎可以工作。下一个增强功能是弄清楚如何捕获将折叠逻辑应用于新数据(验证集或将来的数据)的“规则”。

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

Answers:


11

看来,这只是“重新调整”因素的问题。无需计算部分和或复制原始向量。例如,

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"

在这里,原始因子水平分配如下:

 A  B  C  D  E 
18 23 35 36 38 

然后变成

Other     C     D     E 
   41    35    36    38 

它可以方便地包装成一个函数。reshape软件包中有一个combine_factor()功能,因此我想它也可能很有用。

另外,您似乎对数据挖掘感兴趣,因此可以看一下插入符号包。它具有许多用于数据预处理的有用功能,包括诸如nearZeroVar()允许标记预测值与观测值的分布非常不平衡的功能(请参见插图,例如示例数据,预处理功能,可视化和其他功能,例如第5页)。使用)。


@CHI谢谢。我研究了插入符号包,并用它来调整元参数。很有用!。
B_Miner 2010年

@chl +1,不错。我之所以编写函数,完全是因为代码a [levels(a)%in%lf] <-“ Other”不起作用,所以我认为因素水平的变化很复杂。像往常一样,事实证明R并不复杂,我是:)
mpiktas 2010年

@mpiktas Thx。您可以使用例如在矢量级别上工作a[as.character(a) %in% lf] <- lf[1]; a <- factor(droplevels(a), labels=c("Other",LETTERS[3:5]))
chl 2010年

+1。a [levels(a)%in%lf] <-“其他”肯定会节省大量代码行。聪明高效!
Christopher Aden 2010年

但是请注意,a [a ==“ a”] <-“ Other”将不起作用,对我来说,很自然地认为应该这样做。特别是因为a [a ==“ a”]是完全有效的。
mpiktas 2010年

5

克里斯托弗(Christopher)回答的唯一问题是,它将混合因子的原始顺序。这是我的解决方法:

 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.levels以下功能在哪里?我前一段时间写过它,所以我怀疑可能会有更好的方法来实现它的功能。

 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

我写了一个快速功能来实现这个目标。我是R新手,所以使用大表可能会很慢。

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

举一个实际的例子:

> 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"

约翰,感谢您的观察。我做了一些改动以使其成为一个因素。我所做的只是从表中重新制作了原始向量,因此,如果有一种方法可以跳过该步骤,则会更快。
Christopher Aden 2010年

感谢大家的回应。我的R很弱,但是用很少的代码行就能做到这一点证明了它的功能强大,使我想学习。
B_Miner 2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.