如何基于freq趋势为R数据框分配颜色代码col_mut?
R数据框按freq趋势分配颜色列的实现方法
核心思路
- 按
ID分组,确保每组内记录按Pass排序(保证趋势判断的顺序正确) - 将字符型
freq转换为数值型,处理可能的缺失值 - 针对每组的
freq序列定义趋势判断规则,匹配对应十六进制颜色 - 将颜色映射到该组所有行,生成
col_mut列
具体实现代码
# 加载dplyr用于分组处理 library(dplyr) # 构造示例数据(与需求输入一致) df <- tibble( ID = c(rep("A",4), rep("B",4), rep("C",4), rep("D",4), rep("E",4), rep("F",4)), Pass = rep(1:4,6), freq = c("010","100","100","100", "010","100","010","100", "025","050","075","100", "100","075","050","025", "010","010","010","100", "010","100","100","010") ) # 数据预处理:转换freq为数值型,按ID和Pass排序 df <- df %>% mutate(freq = as.numeric(freq)) %>% arrange(ID, Pass) # 定义趋势判断函数,返回对应颜色 get_trend_color <- function(freq_vec) { # 过滤缺失值,保留有效数据 freq_clean <- freq_vec[!is.na(freq_vec)] # 有效数据不足2个时返回默认灰色 if (length(freq_clean) < 2) return("#cccccc") # 计算相邻值的变化方向(上升=1,下降=-1,不变=0) diff_signs <- sign(diff(freq_clean)) # 匹配需求中的各类趋势 # 立即上升后保持(ID A) if (diff_signs[1] == 1 && all(diff_signs[-1] == 0)) { return("#008000") } # 逐步持续增长(ID C) else if (all(diff_signs == 1)) { return("#d61a33") } # 逐步持续下降(ID D) else if (all(diff_signs == -1)) { return("#2e2eb8") } # 长期低水平后最后一次上升(ID E) else if (all(diff_signs[-length(diff_signs)] == 0) && diff_signs[length(diff_signs)] == 1) { return("#d6811a") } # 上升-下降-上升波动(ID B) else if (sum(diff_signs == 1) == 2 && sum(diff_signs == -1) == 1) { return("#807a00") } # 上升-保持-下降(ID F) else if (diff_signs[1] == 1 && diff_signs[2] == 0 && diff_signs[3] == -1) { return("#b62eb8") } # 未匹配到的趋势返回默认灰色 else { return("#cccccc") } } # 分组应用函数,生成col_mut列 df_result <- df %>% group_by(ID) %>% mutate(col_mut = get_trend_color(freq)) %>% ungroup() # 查看结果 print(df_result)
关键说明
- 数据预处理:必须将
freq转换为数值型才能计算变化趋势;按ID和Pass排序是核心,确保趋势判断基于正确的顺序维度 - 缺失值处理:函数中直接过滤缺失值,若有效数据过少返回灰色;如果需要保留缺失值并参与判断,可改用插值(如
zoo::na.approx)填充后再计算 - 趋势扩展:如果有更多趋势类型,只需在
get_trend_color函数中添加对应的判断分支和颜色映射即可 - 适配多行场景:函数基于整个
freq序列的变化判断趋势,无论每个ID有多少行都能正常工作
内容的提问来源于stack exchange,提问作者Paolo Lorenzini
相关产品推荐
相关产品推荐

