2015-06-26 178 views
2

在RI的早期版本中可以結合未使用下面的小功能,具有體積「顯著」門檻因子水平:結合因子水平3.2.1

whittle = function(data, cutoff_val){ 
    #convert to a data frame 
    tab = as.data.frame.table(table(data)) 
    #returns vector of indices where value is below cutoff_val 
    idx = which(tab$Freq < cutoff_val) 
    levels(data)[idx] = "Other" 
    return(data) 
} 

這需要一個因素矢量,尋找不「經常出現」的級別,並將所有這些級別合併爲一個「其他」級別。這方面的一個例子如下:

> sort(table(data$State)) 

    05 27 35 40 54 84  9 AP AU BE BI DI  G GP GU GZ HN HR JA JM KE KU  L LD LI MH NA 
    1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1 
    OU  P PL RM SR TB TP TW  U VD VI VS WS  X ZH 47 BL BS DL  M MB NB RP TU 11 DU KA 
    1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  2  2  2  2  2  2  2  2  2  3  3  3 
    BW ND NS WY AK SD 13 QC 01 BC MT AB HE ID  J NO LN NM ON NE VT UT IA MS AO AR ME 
    4  4  4  4  5  5  6  6  7  7  7  8  8  8  9 10 11 17 23 26 26 30 31 31 38 40 44 
    OR KS HI NV WI OK KY IN WV AL CO WA MN NH MO SC LA TN AZ IL NC MI GA OH ** CT DE 
    45 47 48 57 57 64 106 108 112 113 120 125 131 131 135 138 198 200 233 492 511 579 645 646 840 873 1432 
    RI DC TX MA FL VA MD CA NJ PA NY 
1782 2513 6992 7027 10527 11016 11836 12221 15485 16359 34045 

現在,當我使用whittle它返回我以下消息:

> delete = whittle(data$State, 1000) 
Warning message: 
In `levels<-`(`*tmp*`, value = c("Other", "Other", "Other", "Other", : 
    duplicated levels in factors are deprecated 

如何修改我的功能,使之具有同樣的效果,但沒有按」噸使用這些「不推薦」的因素水平?轉換爲字符,製表,然後轉換爲字符「其他」?

+3

這將是很好,如果你使這個例子[reproducible](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example)通過包括樣本輸入數據我們可以用來測試可能的解決方案。 – MrFlick

回答

7

測試它我總是發現最容易(更少的輸入和更少的頭痛)轉換爲字符和後面這幾類業務。你as.data.frame.table保持並使用replace做更換低頻層次:

whittle <- function(data, cutoff_val) { 
    tab = as.data.frame.table(table(data)) 
    factor(replace(as.character(data), data %in% tab$data[tab$Freq < cutoff_val], "Other")) 
} 

測試的一些樣本數據:

state <- factor(c("MD", "MD", "MD", "VA", "TX")) 
whittle(state, 2) 
# [1] MD MD MD Other Other 
# Levels: MD Other 
+0

爲了簡潔起見,將其標記爲我的答案。謝謝@josilber – Moderat

5

我認爲這個版本應該可以工作。 levels<-函數允許您通過分配列表來摺疊(請參閱?levels)。

whittle <- function(data, cutoff_val){ 
    tab <- table(data) 
    shouldmerge <- tab < cutoff_val 
    tokeep <- names(tab)[!shouldmerge] 
    tomerge <- names(tab)[shouldmerge] 
    nv <- c(as.list(setNames(tokeep,tokeep)), list("Other"=tomerge)) 
    levels(data)<-nv 
    return(data) 
} 

我們與

set.seed(15) 
x<-factor(c(sample(letters[1:10], 100, replace=T), sample(letters[11:13], 10, replace=T))) 
table(x) 
# x 
# a b c d e f g h i j k l m 
# 5 11 8 8 7 5 13 14 14 15 2 3 5 

y <- whittle(x, 9) 
table(y) 
# y 
#  b  g  h  i  j Other 
# 11 13 14 14 15 43 
2

這是一個被替換下的所有項目做的另一種方式與第一個閾值,然後將該級別重命名爲其他。

whittle <- function(x, thresh) { 
    belowThresh <- names(which(table(x) < thresh)) 
    x[x %in% belowThresh] <- belowThresh[1] 
    levels(x)[levels(x) == belowThresh[1]] <- "Other" 
    factor(x) 
} 
3

值得加入到這個答案,新的forcats包包含fct_lump()功能這是專門爲這一點。

使用@ MrFlick的數據:

x <- factor(c(sample(letters[1:10], 100, replace=T), 
       sample(letters[11:13], 10, replace=T))) 

library(forcats) 
library(magrittr) ## for %>% ; could also load dplyr 
fct_lump(x, n=5) %>% table 

# b  g  h  i  j Other 
#11 13 14 14 15 43 

n參數指定最常見的值來保存數量。