【发布时间】:2013-06-17 10:28:52
【问题描述】:
假设我有一个字符串列表:
string = c("G1:E001", "G2:E002", "G3:E003")
现在我希望得到一个字符串向量,它只包含冒号“:”之后的部分,即substring = c(E001,E002,E003)。
R 中有没有方便的方法来做到这一点?使用substr?
【问题讨论】:
假设我有一个字符串列表:
string = c("G1:E001", "G2:E002", "G3:E003")
现在我希望得到一个字符串向量,它只包含冒号“:”之后的部分,即substring = c(E001,E002,E003)。
R 中有没有方便的方法来做到这一点?使用substr?
【问题讨论】:
例如使用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)straplyc
strapplyc 返回括号部分:
library(gsubfn)
strapplyc(string, ":(.*)", simplify = TRUE)
## [1] "E001" "E002" "E003"
6) 读取.dcf
只有在冒号之前的子字符串是唯一的(它们在问题的示例中)时才有效。它还要求分隔符是冒号(这是问题)。如果使用不同的分隔符,那么我们可以先使用sub 将其替换为冒号。例如,如果分隔符是_,那么string <- sub("_", ":", string)
c(read.dcf(textConnection(string)))
## [1] "E001" "E002" "E003"
7) 分开
7a) 使用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 生成数据框:
library(dplyr)
library(tidyr)
DF %>%
separate(string, into = c(NA, "post")) %>%
unlist %>%
unname
## [1] "E001" "E002" "E003"
8) trimws我们可以使用trimws将单词字符从左边剪掉,然后再次使用它来剪掉冒号。
trimws(trimws(string, "left", "\\w"), "left", ":")
## [1] "E001" "E002" "E003"
输入string 假定为:
string <- c("G1:E001", "G2:E002", "G3:E003")
【讨论】:
_ 作为分隔符的熔化表中有一个变量,并根据@Grothendieck 的答案为前缀和后缀创建了两个单独的变量:prefix <- sub("_.*", "", variable) 和suffix <- sub(".*_", "", variable)
应该这样做:
gsub("[A-Z][1-9]:", "", string)
给予
[1] "E001" "E002" "E003"
【讨论】:
这是另一个简单的答案
gsub("^.*:","", string)
【讨论】:
晚了,但为了后代,stringr 包(流行的“tidyverse”包套件的一部分)现在提供具有协调签名的字符串处理函数:
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() 是一个自然的选择:
tstrsplit(string, ":")[[2]]
[1] "E001" "E002" "E003"
【讨论】:
unglue 包提供了另一种选择,对于简单的情况不需要了解正则表达式,我们会这样做:
# 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 package (v0.3.0) 于 2019 年 11 月 6 日创建
更多信息: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))
【讨论】: