2016-07-27 71 views
3

在python中,scikit有一個很好的功能叫做LabelEncoder,它將分類層次(字符串)映射爲整型表示。R中的標籤編碼器功能?

有沒有什麼在R做這個?例如,如果有一個名爲色用值{「藍」,「紅」,「綠」}可變編碼器將轉變:

Blue => 1 
Green => 2 
Red => 3 

,並用此映射,以再用於轉化新的數據使用創建一個對象以類似的方式。

地址: 似乎不只是因素會起作用,因爲沒有持續的映射。如果新數據與訓練數據有一個看不見的級別,則整個結構會發生變化。理想情況下,我希望以某種方式標記失蹤或「其他」的新級別。

sample_dat <- data.frame(a_str=c('Red','Blue','Blue','Red','Green')) 
sample_dat$a_int<-as.integer(as.factor(sample_dat$a_str)) 
sample_dat$a_int 
#[1] 3 1 1 3 2 
sample_dat2 <- data.frame(a_str=c('Red','Blue','Blue','Red','Green','Azure')) 
sample_dat2$a_int<-as.integer(as.factor(sample_dat2$a_str)) 
sample_dat2$a_int 
# [1] 4 2 2 4 3 1 
+2

R中的因子被編碼爲整數。不確定你的「要求」究竟是什麼。 – MrFlick

+0

將因素作爲一個一致的索引字符串整數未來的數據?我會在我的問題中顯示一個例子 –

+0

如果您明確列出因子可以保持的級別,他們可以。 – MrFlick

回答

1

我寫的,我認爲作品;下面,和/或如何將規模尚未被測試的效率

str2Int.fit_transform<-function(df, plug_missing=TRUE){ 

    list_of_levels=list() #empty list 

    #loop through the columns 
    for (i in 1: ncol(df)) 
    { 

    #only 
    if (is.character(df[,i]) || is.factor(df[,i])){ 

     #deal with missing 
     if(plug_missing){ 

     #if factor 
     if (is.factor(df[,i])){ 
      df[,i] = factor(df[,i], levels=c(levels(df[,i]), 'MISSING')) 
      df[,i][is.na(df[,i])] = 'MISSING' 


     }else{ #if character 

      df[,i][is.na(df[,i])] = 'MISSING' 

     } 
     }#end missing IF 

     levels<-unique(df[,i]) #distinct levels 
     list_of_levels[[colnames(df)[i]]] <- levels #set list with name of the columns to the levels 
     df[,i] <- as.numeric(factor(df[,i], levels = levels)) 

    }#end if character/factor IF 


    }#end loop 

    return (list(list_of_levels,df)) #return the list of levels and the new DF 

}#end of function 



str2Int.transform<-function(df,list_of_levels,plug_missing=TRUE) 
{ 
    #loop through the columns 
    for (i in 1: ncol(df)) 
    { 

    #only 
    if (is.character(df[,i]) || is.factor(df[,i])){ 


     #deal with missing 
     if(plug_missing){ 

     #if factor 
     if (is.factor(df[,i])){ 
      df[,i] = factor(df[,i], levels=c(levels(df[,i]), 'MISSING')) 
      df[,i][is.na(df[,i])] = 'MISSING' 


     }else{ #if character 

      df[,i][is.na(df[,i])] = 'MISSING' 

     } 
     }#end missing IF 

     levels=list_of_levels[[colnames(df)[i]]] 

     if (! is.null(levels)){ 
     df[,i] <- as.numeric(factor(df[,i], levels = levels)) 
     } 

    }# character or factor 

    }#end of loop 

    return(df) 

}#end of function 




###################################################### 
# Test the functions 
###################################################### 



###Test fit transform 

# as strings 
sample_dat <- data.frame(a_fact=c('Red','Blue','Blue',NA,'Green'), a_int=c(1,2,3,4,5), a_str=c('a','b','c','a','v'),stringsAsFactors=FALSE) 

result<-str2Int.fit_transform(sample_dat) 
result[[1]] #list of levels 
result[[2]] #transformed df 

#as factors 
sample_dat <- data.frame(a_fact=c('Red','Blue','Blue',NA,'Green'), a_int=c(1,2,3,4,5), a_str=c('a','b','c','a','v'),stringsAsFactors=TRUE) 

result<-str2Int.fit_transform(sample_dat) 
result[[1]] #list of levels 
result[[2]] #transformed df 



###Test transform 
str2Int.transform(sample_dat,result[[1]]) 
+1

最重要的是,您的解決方案適用於輸入有不完整,新數據和缺失數據的情況。做得好。我測試了這個:'new_dat < - data.frame(a_fact = c('Green','purple','Blue'), a_int = c(1,2,3), a_str = c('z' ,'a',NA), stringsAsFactors = FALSE); str2Int.transform(new_dat,result [[1]]); #a_fact a_int a_str #1 4 1不適用 #2不適用2 1 #3 2 3不適用(這是很難看的..但它是正確的) – geneorama

+0

我做了一些更改,並添加了一些測試/示例。我肯定會在geneorama(我的個人包)中使用它。我唯一想要的其他事情就是用指示變量生成輸出矩陣的方法。不應該太難。 https://gist.github.com/geneorama/02e4e6edb2070d8873377e09d3ecc5d9 – geneorama

5

創建數據的載體:

colors <- c("red", "red", "blue", "green") 

創建一個因素:

factors <- factor(colors) 

轉換系數爲數字:

as.numeric(factors) 

輸出:(注意,這按字母順序排列)

# [1] 3 3 1 2 

您還可以設置自定義編號系統:(注意,現在輸出遵循「彩虹色序」我定義的)

rainbow <- c("red","orange","yellow","green","blue","purple") 
ordered <- factor(colors, levels = rainbow) 
as.numeric(ordered) 
# [1] 1 1 5 4 

?factor

+2

這似乎很好。我想知道是否有任何庫已經創建了處理步驟(Caret沒有),或者需要從頭開始編碼(以便最初進行轉換,並且還可以創建用於稍後應用編碼的字典)。 –

5

如果我正確理解你想要什麼:

# function which returns function which will encode vectors with values of 'vec' 
label_encoder = function(vec){ 
    levels = sort(unique(vec)) 
    function(x){ 
     match(x, levels) 
    } 
} 

colors = c("red", "red", "blue", "green") 

color_encoder = label_encoder(colors) # create encoder 

encoded_colors = color_encoder(colors) # encode colors 
encoded_colors 

new_colors = c("blue", "green", "green") # new vector 
encoded_new_colors = color_encoder(new_colors) 
encoded_new_colors 

other_colors = c("blue", "green", "green", "yellow") 
color_encoder(other_colors) # NA's are introduced 

# save and restore to disk 
saveRDS(color_encoder, "color_encoder.RDS") 
c_encoder = readRDS("color_encoder.RDS") 
c_encoder(colors) # same result 

# dealing with multiple columns 

# create data.frame 
set.seed(123) # make result reproducible 
color_dataframe = as.data.frame(
    matrix(
     sample(c("red", "blue", "green", "yellow"), 12, replace = TRUE), 
     ncol = 3) 
) 
color_dataframe 

# encode each column 
for (column in colnames(color_dataframe)){ 
    color_dataframe[[column]] = color_encoder(color_dataframe[[column]]) 
} 
color_dataframe 
+0

哇....我希望我明白這是做什麼,但似乎工作。是否有可能運行多個列(應用)並將對象保存到磁盤供以後編碼? –

+0

@B_Miner看到我的補充回答 –

+0

非常令人印象深刻!你能告訴我一個嵌套函數如何工作的草圖嗎? –