根据 R 中另一个变量的平均值重命名分类变量

Rename categorical variable according mean of another variable in R

我想根据另一个连续变量的值重命名一个分类变量。

set.seed(123)
temp <- data.frame(label = as.factor(c(rep(1,5),rep(2,5))), 
                   number = c(runif(5, min =5, max = 12), runif(5,min = 3,max = 8)) ) %>% tibble()

>temp
  label number
   <fct>  <dbl>
 1 1       7.01
 2 1      10.5 
 3 1       7.86
 4 1      11.2 
 5 1      11.6 
 6 2       3.23
 7 2       5.64
 8 2       7.46
 9 2       5.76
10 2       5.28


temp_update <- temp %>% group_by(label) %>%
   mutate(mean_numb = mean(number)) %>% arrange(mean_numb) %>% 
                     mutate(mean_numb=as.factor(round(mean_numb,2))) 


> temp_update
# A tibble: 10 x 3
# Groups:   label [2]
   label number mean_numb
   <fct>  <dbl> <fct>    
 1 2       3.23 5.47     
 2 2       5.64 5.47     
 3 2       7.46 5.47     
 4 2       5.76 5.47     
 5 2       5.28 5.47     
 6 1       7.01 9.63     
 7 1      10.5  9.63     
 8 1       7.86 9.63     
 9 1      11.2  9.63     
10 1      11.6  9.63    

在这个小例子中,因为组2的mean(number)小于组1的mean(number),我想将label == 1重命名为2, label == 2 到 1.

这个例子只是我问题的一个小玩具,想象一下我可以有一个巨大数量的标签。

非常感谢

比我确定的可能要长一些,但这应该可以让您到达那里:

我们首先汇总数据,只从 mean(number) 中获取唯一值,然后使用 rank() 函数找出哪些较大。

然后我们使用 full_join() 将此信息与原始数据放回一起并与 label 列合并。

temp_update <- temp %>% 
  group_by(label) %>%
  summarise(mean_numb = mean(number)) %>% 
  mutate(rank = rank(mean_numb)) %>% 
  
  full_join(temp, by="label") %>% 
  arrange(rank)

您可以确保列的名称现在最终替换了原来的 label 列,使用:

temp_update %>% 
  mutate(label = rank, 
         rank = NULL)

对于每个 label,根据它们的平均值计算 mean numberarrange 数据。然后您可以创建一个新的标签列 (new_label),它只是根据平均值的行号。将此数据与原始数据连接起来以恢复所有行。

library(dplyr)

temp %>%
  group_by(label) %>%
  summarise(mean_num = mean(number)) %>%
  arrange(mean_num) %>%
  mutate(new_label = row_number()) %>%
  inner_join(temp, by = 'label')

#   label mean_num new_label number
#   <fct>    <dbl>     <int>  <dbl>
# 1 2         5.47         1   3.23
# 2 2         5.47         1   5.64
# 3 2         5.47         1   7.46
# 4 2         5.47         1   5.76
# 5 2         5.47         1   5.28
# 6 1         9.63         2   7.01
# 7 1         9.63         2  10.5 
# 8 1         9.63         2   7.86
# 9 1         9.63         2  11.2 
#10 1         9.63         2  11.6 

为了比较,我在最终输出中同时保留了 labelnew_label 列。如果不再需要,您可以使用 %>% select(-label) 删除 label 列。

为了完整起见,这里是使用 data.tablefrank 函数的相同方法(您可能需要调整关系的排名方法,具体取决于您希望如何对两个组进行排名和标记均值相同):

library(data.table)
setDT(temp)
setkey(temp[temp[, .(mean_numb=mean(number)), by=label][, new_label:=frank(mean_numb)], 
            on="label"], new_label)[]
#>     label    number mean_numb new_label
#>  1:     2  3.227782  5.474131         1
#>  2:     2  5.640527  5.474131         1
#>  3:     2  7.462095  5.474131         1
#>  4:     2  5.757175  5.474131         1
#>  5:     2  5.283074  5.474131         1
#>  6:     1  7.013043  9.631682         2
#>  7:     1 10.518136  9.631682         2
#>  8:     1  7.862838  9.631682         2
#>  9:     1 11.181122  9.631682         2
#> 10:     1 11.583271  9.631682         2