将含人员排名的DataFrame转换为按排名排序的品种列表DataFrame
按人员排名顺序整理品种列表
原始数据
我们有如下记录人员对品种排名的数据框:
df <- data.frame( variety = c("variety1","variety2","variety3","variety4","variety5"), people1 = c(1, NA, 3, 2, NA), people2 = c(4, 3, 2, 1, NA), people3 = c(3, 2, 5, 4, 1) ) # 查看原始数据 df #> variety people1 people2 people3 #> 1 variety1 1 4 3 #> 2 variety2 NA 3 2 #> 3 variety3 3 2 5 #> 4 variety4 2 1 4 #> 5 variety5 NA NA 1
需求
需要生成一个数据框,按每名人员的排名顺序(升序)列出对应品种,缺失排名的位置用<NA>填充,目标格式如下:
people1 people2 people3 1 variety1 variety4 variety5 2 variety3 variety3 variety2 3 variety4 variety2 variety1 4 <NA> variety1 variety4 5 <NA> <NA> variety3
解决方案
方法一:基础R实现
无需额外依赖包,通过循环处理每一列:
# 获取所有人员列的列名 people_cols <- grep("people", colnames(df), value = TRUE) # 逐个处理人员列,按排名提取品种 result_list <- lapply(people_cols, function(col) { # 组合品种和当前人员的排名 temp <- df[, c("variety", col)] # 按排名升序排序,NA排在最后 temp_sorted <- temp[order(temp[[col]], na.last = TRUE), ] # 提取品种,统一长度为5,不足的位置补NA out <- temp_sorted$variety length(out) <- nrow(df) out }) # 转换为数据框并设置列名 result_df <- as.data.frame(do.call(cbind, result_list)) colnames(result_df) <- people_cols # 查看结果 result_df
方法二:tidyverse包实现
使用dplyr和tidyr进行数据重塑:
library(tidyverse) result_df <- df %>% # 宽表转长表,拆分人员和排名 pivot_longer(cols = starts_with("people"), names_to = "person", values_to = "rank") %>% # 按人员分组,按排名升序排序 group_by(person) %>% arrange(rank, .by_group = TRUE) %>% # 为每组添加行号 mutate(row = row_number()) %>% # 长表转宽表,还原人员列 pivot_wider(names_from = person, values_from = variety) %>% # 补全到5行,缺失位置填充NA complete(row = 1:nrow(df)) %>% # 移除行号列 select(-row) # 查看结果 result_df
两种方法都能得到符合要求的输出。
内容的提问来源于stack exchange,提问作者user236152
相关产品推荐
相关产品推荐

