You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言杂乱dataframe分块标记行提取为新增标识符列的实现方法

问题描述

现有一个格式杂乱的dataframe,结构为多个观测块循环出现,每个观测块的最后一行是对应块的标记行。该数据来自不可修改/重编程的设备输出,已从存储杂乱字符串的val列中提取出多类字段。
需求为通过匹配标记行中的PD字段识别标记行,将每个块的标记行内容作为标识符存入新增的part列,最终仅保留各块的有效观测行,实现逻辑不受每块观测数量、块总数量限制。

输入示例数据

val<-c("Settle0.90s10.0073", "Settle0.80s10.0070", "Settle0.70s10.0067","   
10/22/2110:51:4100PROG 0        PD    Pass        0.0150",
       "Settle0.90s10.0073", "Settle0.80s10.0070", "Settle0.70s10.0067",
       "10/22/2110:52:0300PROG 0        PD    Pass        0.0086")
type<-c("Settle", "Settle", "Settle",NA,"Settle", "Settle", "Settle",NA)
time_sec<-c(0.90,0.80,0.70,"10/22",0.90,0.80,0.70,"10/22")
sec<-c("s","s","s",NA,"s","s","s",NA)
press_psi<-c(10.0073,10.0070, 10.0067,NA,10.0073,10.0070, 10.0067,NA)

df<-data.frame(val,type,time_sec,press_psi)

期望输出效果

val<-c("Settle0.90s10.0073", "Settle0.80s10.0070", "Settle0.70s10.0067", 
       "Settle0.90s10.0073", "Settle0.80s10.0070", "Settle0.70s10.0067")
type<-c("Settle", "Settle", "Settle","Settle", "Settle", "Settle")
time_sec<-c(0.90,0.80,0.70,0.90,0.80,0.70)
sec<-c("s","s","s","s","s","s")
press_psi<-c(10.0073,10.0070, 10.0067,10.0073,10.0070, 10.0067)
part<-c("10/22/2110:51:4100PROG 0        PD    Pass        0.0150",
        "10/22/2110:51:4100PROG 0        PD    Pass        0.0150",
        "10/22/2110:51:4100PROG 0        PD    Pass        0.0150",
        "10/22/2110:52:0300PROG 0        PD    Pass        0.0086",
        "10/22/2110:52:0300PROG 0        PD    Pass        0.0086",
        "10/22/2110:52:0300PROG 0        PD    Pass        0.0086")
df<-data.frame(val,type,time_sec,press_psi,part)

现有实现问题

已写代码可拆分出各块的有效观测:

lapply(split(df, cumsum(grepl("PD", df$val))), tail, -1)

但需要手动为输出列表中每个dataframe新增part列后再合并,希望有更简便的实现方式。

解决方案

方案1:tidyverse实现(最简洁)

通过向上填充的逻辑直接匹配标记值,无需拆分合并:

library(dplyr)
library(tidyr)

result <- df %>%
  # 仅标记行赋值part内容,去除多余空白符
  mutate(part = ifelse(grepl("PD", val), trimws(val), NA_character_)) %>%
  # 从下往上填充NA,每个块的有效观测自动匹配对应块的标记值
  fill(part, .direction = "up") %>%
  # 过滤掉标记行,仅保留有效观测
  filter(!grepl("PD", val))

方案2:base R实现

无需依赖第三方包:

# 定位所有标记行,提取对应part值
pd_pos <- grep("PD", df$val)
pd_val <- trimws(df$val[pd_pos])
# 为每行分配所属块编号
df$block_id <- findInterval(seq(nrow(df)), pd_pos, rightmost.closed = TRUE)
# 匹配part值
df$part <- pd_val[df$block_id]
# 移除标记行和辅助列,得到最终结果
result <- df[-pd_pos, setdiff(names(df), "block_id")]

两种方案均完全适配任意块长度、任意块总数的场景,仅靠匹配PD识别标记行,无需手动处理列表拆分合并逻辑。


内容的提问来源于stack exchange,提问作者Mushroom Luvin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 12:45:03