有关在R中同时重新编码多个因子水平的问题

时间:2018-10-08 05:26:14

标签: r factors

使用诸如 plyr dplyr 之类的惊人软件包,数据操作轻而易举。重新编码因子级别可能很困难,尤其是对于具有多个级别的变量而言,可以很容易地用这些软件包来完成。但是,对于那些学习数据科学的人来说,了解基本R的工作原理很重要。

我想从R专家那里寻求有关使用基数R重新编码因子的帮助。我的问题是为什么一个符号起作用而另一个符号在R中不起作用。

我生成一个具有五个类别和300个观察值的向量。我将向量转换为因子并生成以下列表。

x <- sample(c("a", "b", "c", "d", "e", "f"), 300, replace = TRUE)
x <-factor(x)

> table(x)
a  b  c  d  e  f 
57 58 51 45 45 44 

> table(as.numeric(x))
 1  2  3  4  5  6 
57 58 51 45 45 44

请注意,通过使用as.numeric选项,我可以看到各个字符符号的内部级别结构。假设我想将类别a和f重新编码为丢失。我可以使用以下代码完成此操作。

x[as.numeric(x) %in% c(1,6)] <- NA
> table(factor(x))
b  c  d  e 
58 51 45 45 

其中1和6对应于a和f。

请注意,我已经使用级别的位置而不是级别本身来将值转换为丢失。

到目前为止很好。

现在让我们假设我想将类别a和f转换为成绩。我认为以下代码可以工作,但是没有用。它会返回各种错误的答案。

# Recode and a and f as grades
x <- sample(c("a", "b", "c", "d", "e", "f"), 300, replace = TRUE)
x <-factor(x)
table(as.numeric(x))
levels(x)[as.numeric(x) %in% c(1,6)] <- "grades"
table(factor(x))
 a      b      c grades      e      f 
46     46     56     52     42     58

但是,当我明确引用级别时,该脚本将按预期工作。请参见下面的脚本。

x <- sample(c("a", "b", "c", "d", "e", "f"), 300, replace = TRUE)
x <-factor(x); table(x)
my.list = c("a", "f")
levels(x)[levels(x) %in% my.list] <- "grades"
table(factor(x)) 
grades      b      c      d      e 
   110     49     40     45     56

因此,问题在于为什么一种方法有效而另一种无效?

2 个答案:

答案 0 :(得分:0)

set.seed(123)
x <- sample(c("a", "b", "c", "d", "e", "f"), 300, replace = TRUE)
x <-factor(x)
table(as.numeric(x))

# 1  2  3  4  5  6 
#44 55 56 49 48 48 

现在,当您尝试更改levels

length(as.numeric(x) %in% c(1,6)) #gives
#[1] 300

length(levels(x)) #is just
#[1] 6

下一步,当您完成

as.numeric(x) %in% c(1,6) #it returns a vector of length 300
#[1] FALSE FALSE FALSE  TRUE  TRUE  TRUE FALSE  TRUE FALSE FALSE  TRUE.......

现在,当您这样做

levels(x)[as.numeric(x) %in% c(1,6)]
#[1] "d" "e" "f" NA  NA  NA  NA  NA  NA  NA .....

将它们全部保留为NA,因为没有更多levels可供选择。

所以

levels(x)[as.numeric(x) %in% c(1,6)] <- "grades"

将“ d”,“ e”和“ f”更改为“成绩”

table(x)
#x
# a      b      c grades 
#44     55     56    145 

但这不是您想要的。

第二次尝试

levels(x)[levels(x) %in% my.list]

它之所以有效,是因为

length(levels(x))
#[1] 6

答案 1 :(得分:0)

您想实现什么?

使用as.numeric()处理因素不是一个好主意,您可能会感到惊讶。可能最喜欢的方法是尽可能避免因素(例如,在创建数据帧时使用stringsAsFactors=FALSE,并使用as.is=TRUEread.csv-read.table使用as.is,因为相反的是as.it.is.not)。与任何带因数的运算相比,操纵字符向量更直接,更不容易出错,并且在技术上需要因数时,在许多情况下,分析功能会考虑到它-否则,通常更容易创建一个具有动态级别的因素(带有级别),并具有适当的级别排序和标签,而不用担心与因素相关的所有混乱。

那..

 levels(x)[as.numeric(x) %in% c(1,6)]

levels(x)是一个长度为6的字符向量,as.numeric(x)是一个长度为300的逻辑向量。因此,您试图索引一个具有更长逻辑向量的短向量。在这样的索引中,索引向量的作用就像一个“开关”,“ TRUE”表示您要在输出中的此位置查看项目,而“ FALSE”表示您不希望看到该项目。那么,您要求levels(x)的哪些元素? (这将是随机的,如果重要的话,您可以使用set.seed使其重现。)

> which(as.numeric(x) %in% c(1,6))
 [1]   4   9  10  12  14  16  24  35  37  44  47  52  54  57  58  61  63  69  79  81  82  83
[23]  84  86  87  89  91  92  99 100 103 109 114 121 124 125 129 134 135 138 140 141 143 147
[45] 154 167 178 179 181 187 188 194 201 212 213 214 217 218 219 220 222 232 235 237 239 245
[67] 254 255 258 260 263 265 266 267 275 278 281 286 294 295 296

如果您想通过引用等效的数值来替换某些级别,则完全不需要as.numeric

 levels(x)[c(1,6)] <- "grades"

 > levels(x)[c(1,6)] <- "grades"
 > table(x)
 x
 grades      b      c      d      e 
    101     45     46     62     46

“ a”和“ f”已根据需要由“成绩”代替。鉴于上面的“ as.numeric”,您想到的是级别1和6,但实际上只要求更改级别4。 (确切级别取决于RNG,而不是直接由您控制)。