grep() 和 sub() 以及正则表达式

grep() and sub() and regular expression

我想更改 data.frame 中的变量名称,例如"pmm_StartTimev4_E2_C19_1" 到 "pmm_StartTimev4_E2_C19"。因此,如果名称 以下划线结尾,后跟任何数字 ,它将被删除。

但我希望仅当变量名称中包含单词"Start"时才会发生这种情况。

我遇到了一些无法运行的混乱代码。任何帮助,将不胜感激!

# Current data frame:    
dfbefore <- data.frame(a=c("pmm_StartTimev4_E2_C19_1","pmm_StartTimev4_E2_E2_C1","delivery_C1_C12"),b=c("pmm_StartTo_v4_E2_C19_2","complete_E1_C12_1","pmm_StartTo_v4_E2_C19"))

# Desired data frame:
dfafter <- data.frame(a=c("pmm_StartTimev4_E2_C19","pmm_StartTimev4_E2_E2_C1","delivery_C1_C12"),b=c("pmm_StartTo_v4_E2_C19","complete_E1_C12_1","pmm_StartTo_v4_E2_C19"))

# Current code:
sub((.*{1,}[0-9]*).*","",grep("Start",names(df),value = TRUE)

我们可以使用 sub 来捕获 'Start' 子字符串后跟一个下划线和一个或多个数字的组。在替换中,使用捕获组的反向引用。由于有多个列,使用 lapply 遍历列,应用 sub 并将输出分配回原始数据

out <- dfbefore
out[] <- lapply(dfbefore, sub, 
            pattern = "^(.*_Start.*)_\d+$", replacement ="\1")
out

dfafter[] <- lapply(dfafter, as.character)
all.equal(out, dfafter, check.attributes = FALSE)
#[1] TRUE

使用 gsub() 这样的东西如何?

stripcol <- function(x) {
  gsub("(.*Start.*)_\d+$", "\1", as.character(x))  
}

dfnew <- dfbefore
dfnew[] <- lapply(dfbefore, stripcol)

我们使用正则表达式查找"Start",然后抓取除末尾下划线数字以外的所有内容。我们使用 lapply 将函数应用于所有列。

doit <- function(x){
  x <- as.character(x)
  if(grepl("Start",x)){
    x <- gsub("_([0-9])","",x)
  }
  return(x)
} 


apply(dfbefore,c(1,2),doit)
    a                          b                      
[1,] "pmm_StartTimev4_E2_C19"   "pmm_StartTo_v4_E2_C19"
[2,] "pmm_StartTimev4_E2_E2_C1" "complete_E1_C12_1"    
[3,] "delivery_C1_C12"          "pmm_StartTo_v4_E2_C19"