在不改变值的顺序的情况下重新排列因子的水平

我有一些数字variables和一些分类factorvariables的数据框架。 这些因素的级别顺序不是我想要的。

 numbers <- 1:4 letters <- factor(c("a", "b", "c", "d")) df <- data.frame(numbers, letters) df # numbers letters # 1 1 a # 2 2 b # 3 3 c # 4 4 d 

如果我改变关卡的顺序,那么这些关键字就不再有相应的数字了(我的数据从这个意义上说是无稽之谈)。

 levels(df$letters) <- c("d", "c", "b", "a") df # numbers letters # 1 1 d # 2 2 c # 3 3 b # 4 4 a 

我只是想改变水平的顺序,所以当绘图,酒吧显示所需的顺序 – 这可能会有所不同,默认的字母顺序。

使用factorlevels参数:

 df <- data.frame(f = 1:4, g = letters[1:4]) df # fg # 1 1 a # 2 2 b # 3 3 c # 4 4 d levels(df$g) # [1] "a" "b" "c" "d" df$g <- factor(df$g, levels = letters[4:1]) # levels(df$g) # [1] "d" "c" "b" "a" df # fg # 1 1 a # 2 2 b # 3 3 c # 4 4 d 

还有一些,只是为了logging

 ## reorder is a base function df$letters <- reorder(df$letters, new.order=letters[4:1]) library(gdata) df$letters <- reorder.factor(df$letters, letters[4:1]) 

你也可能会发现有用的Relevel和combine_factor 。

所以在R词典中,你只需要改变给定因子variables的标签 (即保留数据以及因子水平不变)。

 df$letters = factor(df$letters, labels=c("d", "c", "b", "a")) 

假设您只想更改数据点到标签的映射关系,而不是数据或因子模式(数据点如何分为单独的元素或因子值,那么在初始创build时可能会知道最初设置映射的方式因素。

规则很简单:

  • 标签通过索引值被映射到级别(即,级别[2]处的值被赋予标签,标签[2]);
  • 因子水平可以通过在水平参数中传递它们来显式设置; 要么
  • 如果不为levels参数提供值,则使用默认值,这是对传入的数据向量唯一的结果(对于数据参数)。
  • 标签可以通过标签参数显式设置; 要么
  • 如果标签参数没有提供任何值,则使用默认值,这就是水平向量

在R中处理因素是相当奇特的工作,我必须承认…在重新sorting因子水平时,您不会重新排列基础数值。 这里有一个示例:

 > numbers = 1:4 > letters = factor(letters[1:4]) > dtf <- data.frame(numbers, letters) > dtf numbers letters 1 1 a 2 2 b 3 3 c 4 4 d > sapply(dtf, class) numbers letters "integer" "factor" 

现在,如果您将此因子转换为数字,您将得到:

 # return underlying numerical values 1> with(dtf, as.numeric(letters)) [1] 1 2 3 4 # change levels 1> levels(dtf$letters) <- letters[4:1] 1> dtf numbers letters 1 1 d 2 2 c 3 3 b 4 4 a # return numerical values once again 1> with(dtf, as.numeric(letters)) [1] 1 2 3 4 

正如你所看到的……通过改变关卡,你只能改变关卡(谁会说,呃?),而不是数值! 但是,当你使用factor函数@Jonathan Changbuild议时,会发生一些不同的情况:你自己改变数值。

你再次遇到错误,因为你做的levels ,然后尝试与factor 。 不要这样做! 不要使用levels否则你会搞砸(除非你确切地知道你在做什么)。

一个小小的build议:避免用与R的对象相同的名称来命名对象( df是F分布的密度函数, letters给出小写字母)。 在这个特殊情况下,你的代码不会有问题,但有时候可能是…但是这会造成混乱,我们不希望这样做,我们呢? =)

相反,使用这样的东西(我会再次从头开始):

 > dtf <- data.frame(f = 1:4, g = factor(letters[1:4])) > dtf fg 1 1 a 2 2 b 3 3 c 4 4 d > with(dtf, as.numeric(g)) [1] 1 2 3 4 > dtf$g <- factor(dtf$g, levels = letters[4:1]) > dtf fg 1 1 a 2 2 b 3 3 c 4 4 d > with(dtf, as.numeric(g)) [1] 4 3 2 1 

请注意,您也可以使用dfletters而不是g来命名data.frame ,结果是OK。 实际上,这个代码和你发布的代码是一样的,只是名字被改变了。 这部分factor(dtf$letter, levels = letters[4:1])不会抛出一个错误,但它可以混淆!

仔细阅读?factor手册! factor(g, levels = letters[4:1])factor(g, labels = letters[4:1])之间有什么区别? levels(g) <- letters[4:1]g <- factor(g, labels = letters[4:1])什么相似之处?

你可以把ggplot的语法,所以我们可以帮助你在这一个更多!

干杯!!!

编辑:

ggplot2实际上需要更改两个级别和值? 嗯…我会把这个挖出来…

由于这个问题是最后的活动,哈德利已经发布了他的新的forcats包操纵因素,我发现它非常有用。 来自OP的数据框的例子:

 levels(df$letters) # [1] "a" "b" "c" "d" 

要扭转关卡:

 library(forcats) fct_rev(df$letters) %>% levels # [1] "d" "c" "b" "a" 

要添加更多级别:

 fct_expand(df$letters, "e") %>% levels # [1] "a" "b" "c" "d" "e" 

还有更多有用的fct_xxx()函数。

我想补充一个例子,其中的级别可以是string和一些特殊字符,如下面的例子

 df <- data.frame(x = c("15-25", "0-4", "5-10", "11-14", "100+")) 

x的默认级别是:

 df$x # [1] 15-25 0-4 5-10 11-14 100+ # Levels: 0-4 100+ 11-14 15-25 5-10 

在这里,如果我们想根据数值重新排列因子水平,而不明确写出水平,我们可以做的是

 library(gtools) df$x <- factor(df$x, levels = mixedsort(df$x)) df$x # [1] 15-25 0-4 5-10 11-14 100+ # Levels: 0-4 5-10 11-14 15-25 100+ as.numeric(df$x) # [1] 4 1 2 3 5 

我希望这可以作为未来读者的有用信息。