R语言查找DataFrame中比当前值低20%的首个后续行对应日期
R语言实现DataFrame按行匹配后续首个阈值触发行的方案
原有代码的问题排查
- 循环范围错误:
for(i in length(df))只会遍历最后1行,应改为遍历1到总行数 - 赋值范围错误:每次循环给整列
df$conc20赋值,会覆盖之前所有行的计算结果,应仅给第i行赋值 - 匹配范围错误:未限定仅查找当前行之后的样本,会匹配到历史行不符合业务逻辑
- 无异常处理:未考虑后续无符合条件行的场景,会返回错误值
正确实现方案
方案1:基础R原生for循环(易理解,无需额外依赖)
首先需要确保数据按日期升序排列,保证「后续行」的时间逻辑正确:
# 按日期升序排序 df <- df[order(df$date), ] total_row <- nrow(df) # 初始化conc20列,类型和date列保持一致 df$conc20 <- as.Date(NA, origin = "1970-01-01") for (i in 1:total_row) { # 仅取当前行之后的样本做匹配 follow_samples <- df$sample[(i + 1):total_row] threshold <- df$sample[i] * 0.8 # 取第一个符合条件的位置 first_match_idx <- which(follow_samples < threshold)[1] # 匹配成功则写入对应日期 if (!is.na(first_match_idx)) { df$conc20[i] <- df$date[i + first_match_idx] } }
方案2:tidyverse简洁实现(代码更精简)
依托dplyr和purrr包实现向量化运算:
library(dplyr) library(purrr) df <- df %>% arrange(date) %>% # 按日期升序排序保证逻辑正确 mutate(conc20 = map2_chr(sample, row_number(), function(cur_val, cur_rn) { threshold <- cur_val * 0.8 # 筛选当前行之后首个符合阈值要求的日期 target_date <- date[cur_rn < row_number() & sample < threshold][1] as.character(target_date) }) %>% as.Date())
效果验证
以你提供的示例第一行数据为例:当前sample值为0.008470,阈值为0.008470*0.8=0.006776,后续首个小于该阈值的样本为2020-02-25的0.006738,和你期望的输出结果一致。
内容的提问来源于stack exchange,提问作者Bo_0
相关产品推荐
相关产品推荐

