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"
我想更改 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"