【问题标题】:How can I replace a factor levels with the top n levels (by number of occurances)如何用前 n 个级别替换因子级别(按出现次数)
【发布时间】:2015-10-28 10:15:25
【问题描述】:

此问题与How can I replace a factor levels with the top n levels (by some metric), plus [other]? 有关。作为一个指标,我想使用该因素的出现次数。我知道我可以通过列出事件列表来做到这一点,但我想知道是否有更漂亮的方法。

例子:

library(data.table);
library(plyr);
fac <- data.table(score = as.factor(c(3,4,5,3,3,3,5)));
ocCnt <- data.table(lapply(fac,count)$score);
fac$occurrence <- 0;
for(i in 1:length(fac$score)){fac$occurrence[i]<-ocCnt[x==fac$score[i]]$freq};

然后我可以使用引用的问题/答案中描述的功能:

hotfactor= function(fac,by,n=10,o="other") {
   levels(fac)[rank(-xtabs(by~fac))[levels(fac)]>n] <- o
   fac
}

继续这个例子,如果我们只想查看我们所做的最流行的因素:

hotfactor(fac$score,fac$occurrence,1);

要得到答案:

[1] 3 其他 3 3 3 其他

级别:其他 3 级

所以我的问题是,我可以在不添加计算出现次数的列表的情况下执行此操作吗?

请注意,我想对 n 个最流行的因素(不仅仅是最流行的因素)执行此操作。

【问题讨论】:

    标签: r


    【解决方案1】:

    使用tablewhich.max

    score <- factor(c(3,4,5,3,3,3,5))
    levels(score)[- which.max(table(score))] <- "other"
    #[1] 3     other other 3     3     3     other
    #Levels: 3 other
    

    显然,这会通过取第一个最大值来打破平局。

    如果要保留前两个级别:

    score <- factor(c(3, 4,5,3,3,3,5), levels =c(4,3,5))
    
    levels(score)[!levels(score) %in% names(sort(table(score), decreasing = TRUE)[1:2])] <- "other"
    #[1] 3     other 5     3     3     3     5    
    #Levels: other 3 5
    

    【讨论】:

    • 但是如果我想要 10 个最受欢迎的因素呢? 1 只是一个例子。
    【解决方案2】:

    如果您不知道需要对多少级别进行分组,比如 90% 的数据并且愿意使用 dplyr,您可以按照以下方式进行操作:

    library(dplyr)
    
    df <- data.frame(
            f = factor(mapply(rep, letters[1:5], 2^(1:5)) %>% unlist(use.names = F))
    )
    
    df %>% 
        count(f, sort = T) %>% 
        mutate(p = cumsum(n) / nrow(df))
    
    #      A tibble: 5 x 3
    #        f     n         p
    #   <fctr> <int>     <dbl>
    # 1      e    32 0.5161290
    # 2      d    16 0.7741935
    # 3      c     8 0.9032258
    # 4      b     4 0.9677419
    # 5      a     2 1.0000000
    
    (top <- df %>% 
        count(f, sort = T) %>% 
        mutate(p = cumsum(n) / nrow(df)) %>%
        filter(cumall(p < .91)) %>% 
        select(f) %>% 
        unlist(use.names = F))
    
    # [1] e d c
    # Levels: a b c d e
    
    levels(df$f) <- factor(c(levels(df$f), 'z'))
    df$f[!df$f %in% top] <- 'z'
    
    df %>% 
        count(f, sort = T) %>% 
        mutate(p = cumsum(n) / nrow(df))
    
    #  A tibble: 4 x 3
    #        f     n         p
    #   <fctr> <int>     <dbl>
    # 1      e    32 0.5161290
    # 2      d    16 0.7741935
    # 3      c     8 0.9032258
    # 4      z     6 1.0000000
    

    【讨论】:

      猜你喜欢
      • 2011-10-04
      • 2016-09-30
      • 2014-02-11
      • 1970-01-01
      • 2018-02-25
      • 2015-07-24
      • 2016-08-21
      • 2013-10-24
      • 2012-09-21
      相关资源
      最近更新 更多