重新排序因子的级别而不更改值的顺序

cra*_*gos 114 r levels

我的数据框有一些数值变量和一些分类factor变量.这些因素的等级顺序不是我希望它们的方式.

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
Run Code Online (Sandbox Code Playgroud)

如果我更改了级别的顺序,则这些字母不再带有相应的数字(我的数据从这一点开始是完全无意义的).

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

我只想更改级别顺序,因此在绘图时,条形图按所需顺序显示 - 可能与默认的字母顺序不同.

Jon*_*ang 113

使用以下levels参数factor:

df <- data.frame(f = 1:4, g = letters[1:4])
df
#   f g
# 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
#   f g
# 1 1 a
# 2 2 b
# 3 3 c
# 4 4 d
Run Code Online (Sandbox Code Playgroud)

  • ggplot2要求我改变两者,级别的顺序(见上文)和数据帧的值的顺序.df < - df [nrow(df):1,]#reverse (7认同)

Geo*_*tas 20

更多,只是为了记录

## 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])
Run Code Online (Sandbox Code Playgroud)

您也可以找到有用的Relevelcombine_factor.

  • 你的第一个答案对我不起作用.但这有效:`重新排序(df $ letters,seq(4,1))` (2认同)
  • 我遇到一种非常奇怪的情况,“重新排序”适用于一个数据集,而不是另一个数据集。在另一个数据集上,它会抛出错误“tapply(X = X, INDEX = x, FUN = FUN, ...) 中的错误:参数“X”丢失,没有默认值”。不确定这个问题的解决方案是什么。我找不到数据集之间的任何相关差异。 (2认同)

dou*_*oug 9

所以你想要的,在R词典中,只改变给定因子变量的标签(即,保留数据和因子水平,不变).

df$letters = factor(df$letters, labels=c("d", "c", "b", "a"))
Run Code Online (Sandbox Code Playgroud)

假设您只想更改数据点到标签的映射而不是数据或因子模式(数据点如何分箱到单个箱或因子值中,那么在最初创建时可能有助于了解映射最初是如何设置的因素.

规则很简单:

  • 标签按索引值映射到级别(即,级别[2]的值被赋予标签,标签[2]);
  • 可以通过levels参数传递它们来明确设置因子级别 ; 要么
  • 如果没有为levels参数提供值,则使用默认值,该值是传入的数据向量上的唯一调用结果(对于data参数);
  • 标签可以通过labels参数显式设置; 要么
  • 如果没有为labels参数提供值,则使用默认值,它只是级别向量

  • 如果使用此方法,则会对您的数据贴错标签. (11认同)
  • 实际上是的,我不知道该如何处理,答案似乎打算为了绘图而错误地标记数据?啊.回到原来的.用户要小心 (4认同)

aL3*_*3xa 6

处理R中的因素是非常奇怪的工作,我必须承认......在重新排序因子水平时,您不会重新排序基础数值.这是一个小小的示范:

> 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" 
Run Code Online (Sandbox Code Playgroud)

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

# 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
Run Code Online (Sandbox Code Playgroud)

正如你所看到的......通过改变等级,你只改变等级(谁会告诉,呃?),而不是数值!但是,当你使用factor@Jonathan Chang建议的函数时,会发生一些不同的事情:你自己改变数值.

你再次犯错误,因为你做了levels,然后尝试重新解决它factor.不要这样做!千万不能使用levels,否则会搞乱了(除非你知道自己在做什么).

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

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

> dtf <- data.frame(f = 1:4, g = factor(letters[1:4]))
> dtf
  f g
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
  f g
1 1 a
2 2 b
3 3 c
4 4 d
> with(dtf, as.numeric(g))
[1] 4 3 2 1
Run Code Online (Sandbox Code Playgroud)

请注意,您也可以data.frame使用dfletters不是命名g,结果将是正常的.实际上,此代码与您发布的代码相同,只更改了名称.这部分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实际上需要改变水平和价值观?嗯......我会挖出这个...


Joe*_*Joe 5

自从上个问题开始活跃以来,Hadley就发布了forcats用于操纵因素的新软件包,我发现它非常有用。OP数据框中的示例:

levels(df$letters)
# [1] "a" "b" "c" "d"
Run Code Online (Sandbox Code Playgroud)

反转级别:

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

要添加更多级别:

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

还有更多有用的fct_xxx()功能。