假设我有一个字符串列表:
string = c("G1:E001", "G2:E002", "G3:E003")
现在我希望得到一个字符串向量,它只包含冒号“ :”后面的部分,即 substring = c(E001,E002,E003)。
substring = c(E001,E002,E003)
在 R 语言中有没有一种方便的方法来做到这一点? 使用 substr?
substr
例如使用 gsub或 sub
gsub
sub
gsub('.*:(.*)','\\1',string) [1] "E001" "E002" "E003"
以下是一些方法:
1)小组
sub(".*:", "", string) ## [1] "E001" "E002" "E003"
2) strsplit
sapply(strsplit(string, ":"), "[", 2) ## [1] "E001" "E002" "E003"
3) read.table
read.table(text = string, sep = ":", as.is = TRUE)$V2 ## [1] "E001" "E002" "E003"
4)子串
这里假设第二部分始终从第4个字符开始(问题中的例子就是这种情况) :
substring(string, 4) ## [1] "E001" "E002" "E003"
4a)子字符串/正则表达式
如果冒号不总是在一个已知的位置,我们可以通过搜索来修改(4) :
substring(string, regexpr(":", string) + 1)
5) strappyc
strapplyc返回括号中的部分:
strapplyc
library(gsubfn) strapplyc(string, ":(.*)", simplify = TRUE) ## [1] "E001" "E002" "E003"
6) read.dcf
只有当冒号前面的子字符串是唯一的(它们在问题中的示例中) ,这种方法才有效。它还要求分隔符是冒号(问题中就是这个)。如果使用不同的分隔符,那么我们可以使用 sub先用冒号替换它。例如,如果分隔符是 _,那么就是 string <- sub("_", ":", string)
_
string <- sub("_", ":", string)
c(read.dcf(textConnection(string))) ## [1] "E001" "E002" "E003"
7)分开
使用 tidyr::separate我们创建了一个包含两列的数据框架,一列用于冒号前的部分,一列用于冒号后的部分,然后提取后者。
tidyr::separate
library(dplyr) library(tidyr) library(purrr) DF <- data.frame(string) DF %>% separate(string, into = c("pre", "post")) %>% pull("post") ## [1] "E001" "E002" "E003"
7b) 也可以使用 separate创建 post列,然后使用 unlist和 unname创建结果数据帧:
separate
post
unlist
unname
library(dplyr) library(tidyr) DF %>% separate(string, into = c(NA, "post")) %>% unlist %>% unname ## [1] "E001" "E002" "E003"
我们可以使用 trimws来修剪左边的单词字符,然后再用它来修剪冒号。
trimws
trimws(trimws(string, "left", "\\w"), "left", ":") ## [1] "E001" "E002" "E003"
假定输入 string为:
string
string <- c("G1:E001", "G2:E002", "G3:E003")
这应该可以:
gsub("[A-Z][1-9]:", "", string)
给予
[1] "E001" "E002" "E003"
这是另一个简单的答案
gsub("^.*:","", string)
Stringr软件包(流行的“整齐宇宙”软件包的一部分)现在为字符串处理提供了具有协调签名的功能:
string <- c("G1:E001", "G2:E002", "G3:E003") # match string to keep stringr::str_extract(string = string, pattern = "E[0-9]+") # [1] "E001" "E002" "E003" # replace leading string with "" stringr::str_remove(string = string, pattern = "^.*:") # [1] "E001" "E002" "E003"
如果你使用 data.table,那么 tstrsplit()是一个自然的选择:
data.table
tstrsplit()
tstrsplit(string, ":")[[2]] [1] "E001" "E002" "E003"
解开胶水包提供了另一种选择,对于简单的情况,不需要正则表达式的知识,这里我们要做的是:
# install.packages("unglue") library(unglue) string = c("G1:E001", "G2:E002", "G3:E003") unglue_vec(string,"{x}:{y}", var = "y") #> [1] "E001" "E002" "E003"
Reprex 软件包于2019-11-06年度创作(0.3.0版)
更多信息: https://github.com/moodymudskipper/unglue/blob/master/README.md
提取子字符串的另一种方法
library(stringr) substring <- str_extract(string, regex("(?<=:).*")) #[1] "E001" "E002" "E003
:
令人惊讶的是,一个非常“基础 R”的解决方案还没有被添加:
string = c("G1:E001", "G2:E002", "G3:E003") regmatches(string, regexpr('E[0-9]+', string))