在R中结合group_by、uncount和mutate转换含重复行的数据框
解决R语言中按行号规则生成目标数据框的问题
可以借助tidyverse工具包实现需求,核心思路是先生成每个ID的完整行序列,再为每个status明确对应的行号区间,最后匹配填充status值:
步骤1:加载依赖包并定义原数据框
library(tidyverse) id <- c(1001, 1001, 1002) status <- c("dog", "cat", "mouse") col3 <- c(5, 8, 4) col4 <- c(9, 9, 6) df <- data.frame(id, status, col3, col4)
步骤2:生成每个ID的完整行序列
先提取每个ID的总行数(col4),再生成从1到总行数的所有行号:
# 获取每个ID的总行数(去重避免重复计算) id_total <- df %>% distinct(id, col4) %>% rename(total = col4) # 生成每个ID的行号序列 id_row_seq <- id_total %>% mutate(row_num = map(total, ~1:.x)) %>% unnest(row_num) %>% select(id, row_num)
步骤3:计算每个status对应的行号区间
为每个status确定起始行(col3)和结束行:同一ID下,当前status的结束行是下一个status的起始行减1,最后一个status的结束行是该ID的总行数:
status_intervals <- df %>% group_by(id) %>% mutate(end_row = lead(col3, default = first(col4)) - 1) %>% ungroup() %>% select(id, status, start_row = col3, end_row)
步骤4:匹配行号与区间,生成结果数据框
将行序列与status区间匹配,未匹配的行填充为"Not assigned":
df_results <- id_row_seq %>% left_join(status_intervals, by = "id") %>% # 筛选行号在当前status区间内,或未匹配到status的行 filter(row_num >= start_row & row_num <= end_row | is.na(status)) %>% # 填充未匹配的status值 mutate(status = ifelse(is.na(status), "Not assigned", status)) %>% # 去重(未匹配行可能产生重复NA记录) distinct(id, row_num, .keep_all = TRUE) %>% arrange(id, row_num) %>% select(id, status)
执行后输出的df_results即为目标数据框。
内容的提问来源于stack exchange,提问作者Zipsa
相关产品推荐
相关产品推荐

