按组平均值重新排序因子水平

3

我经常需要创建一个因子变量,并且希望保留它来自的变量的顺序。我觉得我应该可以通过在新类别变量的每个组内取平均值,然后将其作为排序变量在fct_reorder中使用来实现这一点,但似乎并不起作用。以下是一个简单的例子:

library(tidyverse)
test_data <- mtcars %>% 
  mutate(mpg_cat=case_when(mpg>20 ~ "More than 20",
                           mpg<=20 & mpg>=15 ~ "15-20",
                           mpg<15 ~ "Less than 15")) %>% 
  group_by(mpg_cat) %>% 
  mutate(avg_mpg=mean(mpg),
         mpg_cat=fct_reorder(mpg_cat,avg_mpg))
levels(test_data$mpg_cat) #Want the order to be less than 15, 15-20, More than 20
3个回答

2

在使用mutate之后,只需执行ungroup,然后使用fct_reorder。根据您的代码:

test_data <- mtcars %>% 
  mutate(mpg_cat=case_when(mpg>20 ~ "More than 20",
                           mpg<=20 & mpg>=15 ~ "15-20",
                           mpg<15 ~ "Less than 15")) %>% 
  group_by(mpg_cat) %>% 
  mutate(avg_mpg=mean(mpg)) %>% 
  ungroup() %>% 
  mutate(mpg_cat=fct_reorder(mpg_cat,avg_mpg))
  
levels(test_data$mpg_cat) #Want the order to be less than 15, 15-20, More than 20
[1] "Less than 15" "15-20"        "More than 20"

2
您可以修改管道,通过您创建的平均变量进行排序,并基于此设置有序因子级别:
library(dplyr)

test_data <- mtcars |>
    mutate(
        mpg_cat = case_when(
            mpg > 20 ~ "More than 20",
            mpg <= 20 & mpg >= 15 ~ "15-20",
            mpg < 15 ~ "Less than 15"
        )
    ) |>
    group_by(mpg_cat) |>
    mutate(avg_mpg = mean(mpg)) |>
    ungroup() %>%
    arrange(avg_mpg) |>
    mutate(
        mpg_cat = factor(
            mpg_cat,
            levels = unique(mpg_cat),
            ordered = TRUE
        )
    )

head(test_data$mpg_cat)
# [1] Less than 15 Less than 15 Less than 15 Less than 15 Less than 15 15-20       
# Levels: Less than 15 < 15-20 < More than 20

或者,如果你仅仅是为了排序创建了平均数,你可以跳过所有的分组、创建新变量,并在一开始按照 mpg 排序进行取消分组,这样可以保证 unique(mpg_cat) 的顺序是正确的。

mtcars |>
    arrange(mpg)  |>
    mutate(
        mpg_cat = case_when(
            mpg > 20 ~ "More than 20",
            mpg <= 20 & mpg >= 15 ~ "15-20",
            mpg < 15 ~ "Less than 15"
        )
    ) |>
     mutate(
        mpg_cat = factor(
            mpg_cat,
            levels = unique(mpg_cat),
            ordered = TRUE
        )
    ) 

1

fct_recode 中有一个 .fun 参数,默认为 median。因此,我们可以直接修改级别而不需要分组。

library(dplyr)
library(forcats)
out <- mtcars %>% 
  mutate(mpg_cat=fct_reorder(case_when(mpg>20 ~ "More than 20",
                           mpg<=20 & mpg>=15 ~ "15-20",
                           mpg<15 ~ "Less than 15"), mpg, .fun = "mean"))

-输出

> levels(out$mpg_cat)
[1] "Less than 15" "15-20"        "More than 20"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接