2016-11-10 88 views
4

我試圖如果他們不是在一個載體來改變一個變量的值轉換爲NA值:R:爲什麼「ifelse」將脅迫因子轉換爲整數?

sample <- factor(c('01', '014', '1', '14', '24')) 
df <- data.frame(var1 = 1:6, var2 = factor(c('01', '24', 'none', '1', 'unknown', '24'))) 
df$var2 <- ifelse(df$var2 %in% sample, df$var2, NA) 

出於某種原因,R不保留因子變量的初始值,但把它們轉化成數字序列:

> sample <- factor(c('01', '014', '1', '14', '24')) 
> df <- data.frame(var1 = 1:6, 
        var2 = factor(c('01', '24', 'none', '1', 'unknown', '24'))) 
> class(df$var2) 
[1] "factor" 
> df 
    var1 var2 
1 1  01 
2 2  24 
3 3 none 
4 4  1 
5 5 unknown 
6 6  24 
> df$var2 <- ifelse(df$var2 %in% sample, df$var2, NA) 
> class(df$var2) 
[1] "integer" 
> df 
    var1 var2 
1 1 1 
2 2 3 
3 3 NA 
4 4 2 
5 5 NA 
6 6 3 

爲什麼會發生這種情況,以什麼樣的方式實現我在這裏嘗試的目標?

(我需要使用的因素,而不是整數,爲了不混淆「01」和「1」和我的原始數據集較大,因此使用的因素,而不是字符應該救我一些內存)

+1

嘗試'dplyr :: if_else'。 – tchakravarty

+0

您是否嘗試過在你的'ifelse()'函數中簡單地添加'as.factor()'? 像這樣:當一個3元素的向量有2個字符和1個數字時,'df $ var2 < - as.factor(ifelse(df $ var2%in%sample,df $ var2,NA))' –

+0

默認爲R數字被轉換爲字符。在你的「sample」的例子中,雖然它是字符,但包含所有數值,所以ifelse將其作爲數字返回。如果你想要它是字符,那麼使用as.character():ifelse(var2%in%sample,as.character(var2),NA) –

回答

2

我想達到什麼你正在嘗試做的一個辦法是改變你的因子的水平:

levels(df$var2)[!levels(df$var2) %in% sample] <- NA 

通過改變所有不符合這些水平值將被轉換爲係數NA和結果的水平將是:

df 
    var1 var2 
1 1 01 
2 2 24 
3 3 <NA> 
4 4 1 
5 5 <NA> 
6 6 24 

> df$var2 
[1] 01 24 <NA> 1 <NA> 24 
Levels: 01 1 24 

未知和無值不再在因子水平。 或者,如果你想保持未知,沒有在你的價值觀,你可以試試這個:

df$var2[!df$var2 %in% sample] <- NA 

> df 
    var1 var2 
1 1 01 
2 2 24 
3 3 <NA> 
4 4 1 
5 5 <NA> 
6 6 24 


> df$var2 
[1] 01 24 <NA> 1 <NA> 24 
Levels: 01 1 24 none unknown 

爲什麼ifelse被改變類數據的原因是ifelse不維護類。在這裏閱讀第二個答案:How to prevent ifelse() from turning Date objects into numeric objects

作爲@tchakravarty在評論中提到的最後一種方法是使用dplyr的if_else!