使用R语言dplyr按列计算行分位数/十分位数并插入新列
解决方案
一、核心问题分析
你之前的quantile代码无法运行,是因为across要求传入的是对列中每个元素进行映射的函数,而quantile()本身是返回整列的分位数断点值,不是给每个元素分配对应的分位数组。同时直接用列名切片c(cnam_year2[1]:cnam_year2[length(cnam_year2)])不够安全,建议改用all_of()来引用字符向量中的列名。
二、生成并插入分位数(十分位数)列
方法1:基于分位数断点分组(更贴合统计意义的十分位数)
这种方法会根据每列的实际分位数断点,将每个值分配到对应的十分位组(1-10),自动忽略NA值:
library(dplyr) library(purrr) # 用于后续列排序 # 生成带十分位数列的数据框 decile_result <- yearRetsMSA2 %>% mutate( across( all_of(cnam_year2), ~ cut( ., breaks = quantile(., na.rm = TRUE, probs = seq(0, 1, 0.1)), labels = 1:10, include.lowest = TRUE ), .names = "{.col}_decile" # 新列命名规则:原列名_decile ) ) # 重新排列列,让原年份列和对应的十分位数列相邻 new_col_order <- unlist(purrr::map(cnam_year2, ~ c(.x, paste0(.x, "_decile")))) decile_result_reordered <- decile_result %>% select(all_of(new_col_order))
方法2:基于数据量均分(等数量分组)
如果需要严格将非NA值均分为10组,可使用ntile():
decile_result <- yearRetsMSA2 %>% mutate( across( all_of(cnam_year2), ~ ntile(na.omit(.), 10)[match(., na.omit(.))], # 保留NA位置 .names = "{.col}_decile" ) ) # 同方法1的列排序步骤 new_col_order <- unlist(purrr::map(cnam_year2, ~ c(.x, paste0(.x, "_decile")))) decile_result_reordered <- decile_result %>% select(all_of(new_col_order))
三、生成并插入排名列
基于你原有的排名代码,优化NA处理和列排序逻辑,确保排名列紧跟对应年份列:
rank_result <- yearRetsMSA2 %>% mutate( across( all_of(cnam_year2), ~ rank(., na.last = "keep"), # 保留NA的原始位置,不参与排名 .names = "{.col}_rank" # 新列命名规则:原列名_rank ) ) # 重新排列列,让原年份列和对应的排名列相邻 rank_col_order <- unlist(purrr::map(cnam_year2, ~ c(.x, paste0(.x, "_rank")))) rank_result_reordered <- rank_result %>% select(all_of(rank_col_order))
四、同时生成排名+分位数列
如果需要一次性生成两种衍生列并保持相邻结构:
combined_result <- yearRetsMSA2 %>% mutate( # 生成排名列 across( all_of(cnam_year2), ~ rank(., na.last = "keep"), .names = "{.col}_rank" ), # 生成十分位数列 across( all_of(cnam_year2), ~ cut( ., breaks = quantile(., na.rm = TRUE, probs = seq(0, 1, 0.1)), labels = 1:10, include.lowest = TRUE ), .names = "{.col}_decile" ) ) # 排列列顺序:原年份列 → 排名列 → 十分位数列 combined_col_order <- unlist(purrr::map(cnam_year2, ~ c(.x, paste0(.x, "_rank"), paste0(.x, "_decile")))) combined_result_reordered <- combined_result %>% select(all_of(combined_col_order))
内容的提问来源于stack exchange,提问作者js80
相关产品推荐
相关产品推荐

