改变和重新排序因素

当使用默认值创建因子时,levels 由应用于输入的 as.character 形成,并按字母顺序排序。

charvar <- rep(c("W", "n", "c"), times=c(17,20,14))
f <- factor(charvar)
levels(f)
# [1] "c" "n" "W"

在某些情况下,对 levels(字母/词汇顺序)的默认排序的处理是可以接受的。例如,如果一个人只想要频率,那将是结果:

plot(f,col=1:length(levels(f)))

StackOverflow 文档

但是如果我们想要 levels 的不同排序,我们需要在 levelslabels 参数中指定它(注意这里 order 的含义与有序因子不同,见下文)。根据具体情况,有许多替代方案可以完成该任务。

1.重新定义因素

如果可能,我们可以使用 levels 参数和我们想要的顺序重新创建因子。

ff <- factor(charvar, levels = c("n", "W", "c"))
levels(ff)
# [1] "n" "W" "c"
 
gg <- factor(charvar, levels = c("W", "c", "n"))
levels(gg)
# [1] "W" "c" "n"

当输入电平不同于所需的输出电平时,我们使用 labels 参数使得 levels 参数成为可接受输入值的滤波器,但将因子矢量的电平的最终值留作参数。labels

fm <- factor(as.numeric(f),levels = c(2,3,1),
             labels = c("nn", "WW", "cc"))
levels(fm)
# [1] "nn" "WW" "cc"

fm <- factor(LETTERS[1:6], levels = LETTERS[1:4],  # only 'A'-'D' as input
                 labels = letters[1:4])            # but assigned to 'a'-'d'
fm
#[1] a    b    c    d    <NA> <NA>
#Levels: a b c d

2.使用 relevel 功能

当有一个特定的 level 需要是第一个我们可以使用 relevel。例如,在统计分析的背景下,当测试假设需要 base 类别时,就会发生这种情况。

g<-relevel(f, "n") # moves n to be the first level
levels(g)
# [1] "n" "c" "W"  

可以证实 fg 是相同的

all.equal(f, g)
# [1] "Attributes: < Component `levels`: 2 string mismatches >"
all.equal(f, g, check.attributes = F)
# [1] TRUE

3.重新排序因素

有些情况下,我们需要根据数字,部分结果,计算统计数据或先前的计算来计算 levels。让我们根据 levels频率重新排序

table(g)
# g
#  n  c  W 
# 20 14 17 

reorder 函数是通用的(参见 help(reorder)),但在这种情况下需要:x,在这种情况下是因子; X,与 x 相同长度的数值; 和 FUN,一个应用于 X 的函数,由 x 的级别计算,它确定 levels 的顺序,默认增加。结果与其重新排序的级别相同。

g.ord <- reorder(g,rep(1,length(g)), FUN=sum) #increasing
levels(g.ord)
# [1] "c" "W" "n"

为了得到降序,我们考虑负值(-1

g.ord.d <- reorder(g,rep(-1,length(g)), FUN=sum)
levels(g.ord.d)
# [1] "n" "W" "c"

该因素再次与其他因素相同。

data.frame(f,g,g.ord,g.ord.d)[seq(1,length(g),by=5),] #just same lines
#    f g g.ord g.ord.d
# 1  W W     W       W
# 6  W W     W       W
# 11 W W     W       W
# 16 W W     W       W
# 21 n n     n       n
# 26 n n     n       n
# 31 n n     n       n
# 36 n n     n       n
# 41 c c     c       c
# 46 c c     c       c
# 51 c c     c       c

当存在与因子变量相关的定量变量时,我们可以使用其他函数对 levels 进行重新排序。让我们看一下 iris 数据(help("iris") 获取更多信息),通过使用它的平均值来重新排序 Species 因子 35。

miris <- iris  #help("iris") # copy the data
with(miris, tapply(Sepal.Width,Species,mean))
#    setosa versicolor  virginica 
#     3.428      2.770      2.974 

miris$Species.o<-with(miris,reorder(Species,-Sepal.Width))
levels(miris$Species.o)
# [1] "setosa"     "virginica"  "versicolor"

通常的 boxplot(比如说:with(miris, boxplot(Petal.Width~Species))会按顺序显示 especies: setosaversicolorvirginica 。但是使用有序因子我们得到的物种按其平均值排序 38:

boxplot(Petal.Width~Species.o, data = miris,
        xlab = "Species", ylab = "Petal Width",
        main = "Iris Data, ordered by mean sepal width", varwidth = TRUE,
        col = 2:4) 

StackOverflow 文档

此外,还可以更改 levels 的名称,将它们组合成组,或添加新的 levels。为此,我们使用相同名称 levels 的功能。

f1<-f
levels(f1)
# [1] "c" "n" "W"
levels(f1) <- c("upper","upper","CAP") #rename and grouping
levels(f1)
# [1] "upper" "CAP" 

f2<-f1
levels(f2) <- c("upper","CAP", "Number") #add Number level, which is empty
levels(f2)
# [1] "upper"  "CAP"    "Number"
f2[length(f2):(length(f2)+5)]<-"Number" # add cases for the new level
table(f2)
# f2
#  upper    CAP Number 
#     33     17      6 

f3<-f1
levels(f3) <- list(G1 = "upper", G2 = "CAP", G3 = "Number") # The same using list
levels(f3)
# [1] "G1" "G2" "G3"
f3[length(f3):(length(f3)+6)]<-"G3" ## add cases for the new level
table(f3)
# f3
# G1 G2 G3 
# 33 17  7 

- 有序因素

最后,我们知道 ordered 因子与 factors 不同,第一个用于表示序数据,第二个用于标称数据。首先,改变 levels 对有序因子的顺序是没有意义的,但我们可以改变它的 labels

ordvar<-rep(c("Low", "Medium", "High"), times=c(7,2,4))

of<-ordered(ordvar,levels=c("Low", "Medium", "High"))
levels(of)
# [1] "Low"    "Medium" "High" 

of1<-of
levels(of1)<- c("LOW", "MEDIUM", "HIGH")
levels(of1)
# [1] "LOW"    "MEDIUM" "HIGH"
is.ordered(of1)
# [1] TRUE
of1
# [1] LOW    LOW    LOW    LOW    LOW    LOW    LOW    MEDIUM MEDIUM HIGH   HIGH   HIGH   HIGH  
# Levels: LOW < MEDIUM < HIGH