如何基于指定列内容逐行按字母顺序调整DataFrame列组顺序?
解决方案:逐行按字母顺序调整列组顺序
方法一:Base R 实现
思路:逐行提取每组的字符列(colXa)和数值列(colXb),按字符列的字母顺序排序后,将排序后的数值列对应放回原位置,最后修正数据类型。
# 定义行处理函数 process_row <- function(row) { # 提取当前行的字符列和数值列值 a_cols <- c(row["col2a"], row["col3a"], row["col4a"]) b_cols <- c(row["col2b"], row["col3b"], row["col4b"]) # 按字符列字母顺序获取排序索引 sorted_idx <- order(a_cols) # 重新排列字符和数值列 sorted_a <- a_cols[sorted_idx] sorted_b <- b_cols[sorted_idx] # 将排序后的值替换回原行 row[c("col2a", "col3a", "col4a")] <- sorted_a row[c("col2b", "col3b", "col4b")] <- sorted_b return(row) } # 应用函数到每一行 df_sorted <- as.data.frame(t(apply(df, 1, process_row))) # 修正数值列的数据类型(apply会将所有列转为字符型) df_sorted[, c("col2b", "col3b", "col4b")] <- lapply(df_sorted[, c("col2b", "col3b", "col4b")], as.numeric)
运行后结果:
> df_sorted col1 col2a col2b col3a col3b col4a col4b usr1 usr1 A 50 B 30 C 20 usr2 usr2 A 30 B 50 C 20
方法二:Tidyverse 实现
思路:将数据转为长格式,按用户分组后基于字符列的值排序,再转回宽格式并调整列顺序,全程保留数据类型。
library(tidyverse) df_sorted <- df %>% # 将宽格式转为长格式,拆分组编号和列类型(a/b) pivot_longer( cols = -col1, names_to = c("group", "type"), names_pattern = "col(\\d)([ab])" ) %>% # 按用户分组,在组内基于字符列(type=a)的值排序组顺序 group_by(col1) %>% group_modify(function(.x, .y) { # 获取当前用户的字符列排序后的组顺序 sorted_groups <- .x %>% filter(type == "a") %>% arrange(value) %>% pull(group) # 按排序后的组顺序重新排列当前用户的所有行 .x %>% arrange(factor(group, levels = sorted_groups)) }) %>% ungroup() %>% # 转回宽格式 pivot_wider( names_from = c("group", "type"), names_glue = "col{group}{type}" ) %>% # 调整列顺序为需求格式 select(col1, col2a, col2b, col3a, col3b, col4a, col4b)
运行结果与Base R方法一致,且无需手动修正数据类型。
内容的提问来源于stack exchange,提问作者tlmoore
相关产品推荐
相关产品推荐

