基于Region列将DataFrame后续列文本移至上一行的实现问题
解决方案
需求明确:当Region列内容以!UK_开头时,将该行第二列至最后一列的所有值移到上一行对应位置,同时将当前行的这些列置空。
原代码问题分析
- 仅处理了
House单列,未覆盖所有第二列起的目标列 - 判断条件
Region %in% substr(Region, 1, 3) == "!UK"逻辑错误,无法正确识别目标行 - 采用插入行再排序的方式,逻辑冗余且不符合需求
修正后的dplyr实现
library(dplyr) # 原始数据 df <- tibble( Region = c("AU","USA","CA","USA","!UK_1","AU","USA","CA","!UK_north"), lock = c(1,1,NA,1,NA,1,NA,1,NA), type= c("sale",NA,NA,"target","target",NA,"sale",NA,"target"), House =c("Tagore house","Gandhi house",NA,"Flexible;Tagore house;Gandhi house","Tagore house",NA,"Flexible;Gandhi house","Gandhi house","Gandhi house") ) # 1. 标记目标行(Region以!UK_开头) df <- df %>% mutate(is_uk = startsWith(Region, "!UK_")) # 2. 获取需要移动的列(第二列至最后一列) cols_to_move <- names(df)[-1] # 3. 将目标行的列值赋值给上一行(这里用拼接,如需替换直接改为lead(!!sym(col))) for(col in cols_to_move) { df <- df %>% mutate(!!col := ifelse(lead(is_uk, default = FALSE), paste0(!!sym(col), "; ", lead(!!sym(col))), !!sym(col))) } # 4. 清空目标行的第二列至最后一列 df <- df %>% mutate(across(all_of(cols_to_move), ~ifelse(is_uk, NA, .))) # 移除标记列(可选) df <- df %>% select(-is_uk)
说明
cols_to_move自动获取第二列到最后一列的列名,适配列数变化- 若需求是替换上一行值而非拼接,将
paste0(...)改为lead(!!sym(col))即可 - 遍历所有目标列,确保每一列都被处理
高效版data.table实现(适合大数据集)
library(data.table) setDT(df) # 标记目标行 df[, is_uk := startsWith(Region, "!UK_")] # 获取需要移动的列 cols_to_move <- setdiff(names(df), c("Region", "is_uk")) # 赋值给上一行 df[shift(is_uk, type = "lead"), (cols_to_move) := lapply(cols_to_move, function(col) { paste0(get(col), "; ", shift(get(col), type = "lead")) })] # 清空目标行的列 df[is_uk, (cols_to_move) := NA] # 移除标记列 df[, is_uk := NULL]
内容的提问来源于stack exchange,提问作者potro
相关产品推荐
相关产品推荐

