J'essaie de déterminer si une chaîne est un sous-ensemble d'une autre chaîne. Par exemple:
chars <- "test"
value <- "es"
Je veux retourner TRUE si "valeur" apparaît dans la chaîne "chars". Dans le scénario suivant, je voudrais retourner false:
chars <- "test"
value <- "et"
fixed=TRUE
, sinon vous la traitez comme une expression régulière au lieu d'une chaîne. Voir ma réponse d'octobre 2016.fixed=TRUE
ou vous avez un bug qui gâchera discrètement et subtilement vos données.Réponses:
Utilisez la
grepl
fonctionUtilisez
?grepl
pour en savoir plus.la source
vec <- replicate(100000, paste( sample(letters, 10, replace=TRUE), collapse='') )
.system.time(a <- grepl("abc", vec))
etsystem.time(a <- grepl("abc", vec, fixed=TRUE))
, etfixed=TRUE
est toujours, si quelque chose légèrement plus lent. La différence n'est pas appréciable avec ces cordes courtes, maisfixed=TRUE
ne semble toujours pas être plus rapide. Merci d'avoir souligné, cependant, que c'est sur de longues cordes quifixed=TRUE
prend le vrai coup.Répondre
Soupir, il m'a fallu 45 minutes pour trouver la réponse à cette simple question. La réponse est:
grepl(needle, haystack, fixed=TRUE)
Interprétation
grep
est nommé d' après l'exécutable linux, qui lui - même est un acronyme de « G lobal R REGULIERS E Xpression P Rint », on lirait les lignes d'entrée, puis les imprimer si elles correspondaient aux arguments que vous avez données. "Global" signifiait que la correspondance pouvait se produire n'importe où sur la ligne d'entrée, j'expliquerai "Expression régulière" ci-dessous, mais l'idée est que c'est une façon plus intelligente de faire correspondre la chaîne (R appelle ce "caractère", par exempleclass("abc")
), et "Imprimer" "car il s'agit d'un programme en ligne de commande, l'émission d'une sortie signifie qu'elle imprime sur sa chaîne de sortie.Maintenant, le
grep
programme est essentiellement un filtre, des lignes d'entrée aux lignes de sortie. Et il semble que les Rgrep
fonction prendra également un tableau d'entrées. Pour des raisons qui me sont totalement inconnues (je n'ai commencé à jouer avec R qu'il y a environ une heure), il renvoie un vecteur des index qui correspondent, plutôt qu'une liste de correspondances.Mais, pour revenir à votre question initiale, ce que nous voulons vraiment, c'est savoir si nous avons trouvé l'aiguille dans la botte de foin, une valeur vraie / fausse. Ils ont apparemment décidé de nommer cette fonction
grepl
, comme dans « grep » mais avec un « L ogique » valeur de retour (ils appellent vraies et fausses valeurs logiques, par exempleclass(TRUE)
).Donc, maintenant nous savons d'où vient le nom et ce qu'il est censé faire. Revenons aux expressions régulières. Les arguments, même s'ils sont des chaînes, sont utilisés pour construire des expressions régulières (désormais: regex). Une expression régulière est un moyen de faire correspondre une chaîne (si cette définition vous irrite, laissez-la aller). Par exemple, l'expression régulière
a
correspond au caractère"a"
, l'expression régulièrea*
correspond au caractère"a"
0 ou plusieurs fois, et l'expression régulièrea+
correspondrait au caractère"a"
1 ou plusieurs fois. Par conséquent, dans l'exemple ci-dessus, l'aiguille que nous recherchons1+2
, lorsqu'elle est traitée comme une expression régulière, signifie "un ou plusieurs 1 suivi d'un 2" ... mais la nôtre est suivie d'un plus!Donc, si vous utilisiez le
grepl
paramètre sansfixed
, vos aiguilles seraient accidentellement des meules de foin, et cela fonctionnerait accidentellement assez souvent, nous pouvons voir que cela fonctionne même pour l'exemple de l'OP. Mais c'est un bug latent! Nous devons lui dire que l'entrée est une chaîne, pas une expression régulière, ce qui est apparemment à celafixed
. Pourquoi réparé? Aucune idée, mettez cette réponse dans vos favoris b / c, vous devrez probablement la rechercher 5 fois de plus avant de la mémoriser.Quelques dernières réflexions
Plus votre code est bon, moins vous devez connaître l'historique pour le comprendre. Chaque argument peut avoir au moins deux valeurs intéressantes (sinon il n'aurait pas besoin d'être un argument), les documents listent 9 arguments ici, ce qui signifie qu'il y a au moins 2 ^ 9 = 512 façons de l'invoquer, c'est beaucoup de travail écrire, tester et mémoriser ... découpler de telles fonctions (les séparer, supprimer les dépendances les unes des autres, les choses de chaîne sont différentes de celles de regex sont différentes de celles de vecteur). Certaines options sont également mutuellement exclusives, ne donnent pas aux utilisateurs des façons incorrectes d'utiliser le code, c'est-à-dire que l'invocation problématique doit être structurellement absurde (comme passer une option qui n'existe pas), pas logiquement absurde (où vous devez émettre un avertissement pour l'expliquer). Mettez métaphoriquement: il est préférable de remplacer la porte d'entrée sur le côté du 10e étage par un mur que de suspendre une pancarte qui met en garde contre son utilisation, mais l'une ou l'autre vaut mieux que ni l'une ni l'autre. Dans une interface, la fonction définit à quoi doivent ressembler les arguments, pas l'appelant (parce que l'appelant dépend de la fonction, inférer tout ce que tout le monde voudra l'appeler avec fait que la fonction dépend aussi des appelants et de ce type de dépendance cyclique obstrueront rapidement un système et ne fourniront jamais les avantages escomptés). Méfiez-vous des types équivoques, c'est un défaut de conception que des choses comme inférer tout ce que tout le monde voudrait l'appeler rend également la fonction dépendante des appelants, et ce type de dépendance cyclique obstruera rapidement un système et ne fournira jamais les avantages escomptés). Méfiez-vous des types équivoques, c'est un défaut de conception que des choses comme inférer tout ce que tout le monde voudrait l'appeler rend également la fonction dépendante des appelants, et ce type de dépendance cyclique obstruera rapidement un système et ne fournira jamais les avantages escomptés). Méfiez-vous des types équivoques, c'est un défaut de conception que des choses comme
TRUE
et0
et"abc"
sont tous des vecteurs.la source
grep
filtrage des lignes, pas des cellules.Vous voulez
grepl
:la source
Utilisez cette fonction du
stringi
package:Quelques repères:
la source
Aussi, peut être fait en utilisant la bibliothèque "stringr":
la source
Juste au cas où vous souhaiteriez également vérifier si une chaîne (ou un ensemble de chaînes) contient plusieurs sous-chaînes, vous pouvez également utiliser le '|' entre deux sous-chaînes.
Tu auras
puisque le premier mot a une sous-chaîne "as", et le dernier mot contient une sous-chaîne "at"
la source
Utilisez
grep
ougrepl
mais sachez si vous souhaitez ou non utiliser des expressions régulières .Par défaut,
grep
et apparenté prennent une expression régulière pour correspondre, pas une sous-chaîne littérale. Si vous ne vous attendez pas à cela et que vous essayez de faire correspondre une expression rationnelle non valide, cela ne fonctionne pas:Pour effectuer un véritable test de sous-chaîne, utilisez
fixed = TRUE
.Si vous voulez des regex, tant mieux, mais ce n'est pas ce que l'OP semble demander.
la source
Vous pouvez utiliser
grep
la source
Problème similaire ici: étant donné une chaîne et une liste de mots clés, détectez lesquels, le cas échéant, des mots clés sont contenus dans la chaîne.
Les recommandations de ce fil suggèrent
stringr
'sstr_detect
etgrepl
. Voici les repères dumicrobenchmark
package:En utilisant
puis
nous trouvons
Comme vous pouvez le voir, plus de 5 000 itérations de la recherche par mot-clé en utilisant
str_detect
etgrepl
sur une chaîne et un vecteur de mots-clésgrepl
pratiques , fonctionnent bien mieux questr_detect
.Le résultat est le vecteur booléen
r
qui identifie les éventuels mots clés contenus dans la chaîne.Par conséquent, je recommande d'utiliser
grepl
pour déterminer si des mots clés se trouvent dans une chaîne.la source