Extraire une sous-chaîne selon un motif


136

Supposons que j'ai une liste de chaînes:

string = c("G1:E001", "G2:E002", "G3:E003")

J'espère maintenant obtenir un vecteur de chaîne qui ne contient que les parties après les deux points ":", c'est à dire substring = c(E001,E002,E003).

Existe-t-il un moyen pratique dans R de faire cela? Utilisation substr?

Réponses:


239

Voici quelques moyens:

1) sous

sub(".*:", "", string)
## [1] "E001" "E002" "E003"

2) strsplit

sapply(strsplit(string, ":"), "[", 2)
## [1] "E001" "E002" "E003"

3) lire le tableau

read.table(text = string, sep = ":", as.is = TRUE)$V2
## [1] "E001" "E002" "E003"

4) sous-chaîne

Cela suppose que la deuxième partie commence toujours au 4e caractère (ce qui est le cas dans l'exemple de la question):

substring(string, 4)
## [1] "E001" "E002" "E003"

4a) sous-chaîne / regex

Si les deux points n'étaient pas toujours dans une position connue, nous pourrions modifier (4) en le recherchant:

substring(string, regexpr(":", string) + 1)

5) strapplyc

strapplyc renvoie la partie entre parenthèses:

library(gsubfn)
strapplyc(string, ":(.*)", simplify = TRUE)
## [1] "E001" "E002" "E003"

6) read.dcf

Celui-ci ne fonctionne que si les sous-chaînes précédant les deux points sont uniques (ce qu'elles sont dans l'exemple de la question). Il faut aussi que le séparateur soit deux points (ce qui est dans la question). Si un séparateur différent était utilisé, nous pourrions l'utiliser subpour le remplacer d'abord par deux points. Par exemple, si le séparateur était _alorsstring <- sub("_", ":", string)

c(read.dcf(textConnection(string)))
## [1] "E001" "E002" "E003"

7) séparé

7a) En utilisant tidyr::separatenous créons un bloc de données avec deux colonnes, une pour la partie avant les deux points et une pour après, puis extrayons cette dernière.

library(dplyr)
library(tidyr)
library(purrr)

DF <- data.frame(string)
DF %>% 
  separate(string, into = c("pre", "post")) %>% 
  pull("post")
## [1] "E001" "E002" "E003"

7b) Alternativement separatepeut être utilisé pour simplement créer lepost colonne, puis unlistet unnamela trame de données résultant:

library(dplyr)
library(tidyr)

DF %>% 
  separate(string, into = c(NA, "post")) %>% 
  unlist %>%
  unname
## [1] "E001" "E002" "E003"

8) Trimws Nous pouvons utiliser trimwspour couper les caractères des mots sur la gauche, puis l'utiliser à nouveau pour couper les deux points.

trimws(trimws(string, "left", "\\w"), "left", ":")
## [1] "E001" "E002" "E003"

Remarque

L'entrée stringest supposée être:

string <- c("G1:E001", "G2:E002", "G3:E003")

J'avais une variable dans une table fondue qui avait _comme séparateur et créé deux variables distinctes pour le préfixe et le suffixe en fonction de la réponse @Grothendieck: prefix <- sub("_.*", "", variable)et suffix <- sub(".*_", "", variable)
swihart

Ce serait bien de voir un microbenchmarking de cette réponse incroyable!
patL

25

Par exemple en utilisant gsubousub

    gsub('.*:(.*)','\\1',string)
    [1] "E001" "E002" "E003"

pourriez-vous expliquer ce que ces ». * (* et ainsi de suite exactement? J'ai du mal à recréer cela dans un cadre légèrement différent ...
Peter Pan

1
@PeterPan Ceci capture et renvoie le groupe de caractères apparaissant après les deux points. Si les chaînes à associer sont plus compliquées et que vous souhaitez rester en base R, cela fonctionne bien.
Clark Fitzgerald


9

Tard dans la fête, mais pour la postérité, le paquet stringr (qui fait partie de la populaire suite de paquets "tidyverse") fournit désormais des fonctions avec des signatures harmonisées pour la gestion des chaînes:

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"

2
N'est-ce pas trouver le premier nombre qui commence par un E, plutôt que tout après le colon?
Mark Neal

6

Cela devrait faire:

gsub("[A-Z][1-9]:", "", string)

donne

[1] "E001" "E002" "E003"

3

Si vous utilisez data.tablealors tstrsplit()est un choix naturel:

tstrsplit(string, ":")[[2]]
[1] "E001" "E002" "E003"

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.