R中基于多条件为现有dataframe新增行列的实现(土地利用分类场景)
实现方案
你可以结合dplyr和tidyr的长表转换、分组比较函数实现需求,全程向量化运算,比循环效率高很多,适合大体积数据集使用。
实现代码
library(dplyr) library(tidyr) df_result <- df_old %>% # 把年份列转为长表 pivot_longer(cols = starts_with("Year"), names_to = "Year", values_to = "Landuse_code") %>% # 提取年份数值 mutate(Year = as.integer(gsub("Year", "", Year))) %>% # 按ID分组处理单个地块的变化 group_by(ID) %>% # 标记当前编码和上一监测年份是否发生变化 mutate(change = lag(Landuse_code, default = first(Landuse_code)) != Landuse_code, # 给每个连续相同编码的时间段分配唯一分组ID period_id = cumsum(change)) %>% # 按时间段分组合并计算起止年份 group_by(ID, period_id, Parameter, City, Area) %>% summarise(Start_Year = min(Year), End_Year = max(Year), pre_code = first(Landuse_code), cur_code = last(Landuse_code), .groups = "drop") %>% # 按规则调整结束年份和Landuse拼接字段 mutate(End_Year = ifelse(End_Year == 2015, "present", as.character(End_Year - 1)), Landuse = paste0(pre_code, "-", cur_code)) %>% # 选择输出所需列 select(ID, Parameter, City, Area, Start_Year, End_Year, Landuse)
方案说明
- 第一步先把宽格式存储的年份列转为长格式,方便逐行对比不同监测年份的土地编码变化
- 通过
lag()偏移函数对比当前行和上一行的土地编码,识别出编码发生变更的节点 - 用
cumsum()累加变化标记,给连续相同编码的时间段分配唯一的分组ID,同一时间段的所有行可以合并为一条记录 - 最后按照需求处理起止年份:如果结束年份是最新的2015年就替换为
present,其余阶段的结束年份为下一阶段起始年份减1,再拼接出Landuse字段即可
如果数据集体量特别大,还可以换成data.table语法实现,运算速度会比tidyverse系更快。
内容的提问来源于stack exchange,提问作者Cam
相关产品推荐
相关产品推荐

