首页 文章

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

提问于
浏览
103

我的数据框有一些数值变量和一些分类 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

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

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

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

7 回答

  • 0

    使用 factorlevels 参数:

    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
    
  • 106

    更多,仅供记录

    ## 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])
    

    您可能还会发现有用的Relevelcombine_factor .

  • 19

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

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

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

    规则很简单:

    • 标签按索引值映射到级别(即,级别[2]的值被赋予标签,标签[2]);

    • 因子级别可以通过levels参数传递来明确设置;要么

    • 如果没有为levels参数提供值,则使用默认值,该值是传入的数据向量上的唯一调用结果(对于data参数);

    • 标签可以通过labels参数显式设置;要么

    • 如果没有为labels参数提供值,则使用默认值,它只是级别向量

  • 7

    处理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"
    

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

    # 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
    

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

    你're getting error once again '因为你做 levels 然后尝试用 factor 重新定位它 . 不要这样做! not 使用 levels 或你做'll mess things up (unless you know exactly what you') .

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

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

    > 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
    

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

  • 3

    由于这个问题是最后一个活跃的,Hadley发布了他的新 forcats 包,用于操纵因子和我的数据框:

    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() 函数 .

  • 3

    我希望添加另一种情况,其中级别可以是带有数字的字符串以及一些特殊字符:如下例所示

    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
    

    我希望这可以被视为未来读者的有用信息 .

  • 6

    这是我重新排序给定数据帧的因素的函数:

    reorderFactors <- function(df, column = "my_column_name", 
                               desired_level_order = c("fac1", "fac2", "fac3")) {
    
      x = df[[column]]
      lvls_src = levels(x) 
    
      idxs_target <- vector(mode="numeric", length=0)
      for (target in desired_level_order) {
        idxs_target <- c(idxs_target, which(lvls_src == target))
      }
    
      x_new <- factor(x,levels(x)[idxs_target])
    
      df[[column]] <- x_new
    
      return (df)
    }
    

    用法: reorderFactors(df, "my_col", desired_level_order = c("how","I","want"))

相关问题