web-dev-qa-db-fra.com

Filtrage de la ligne contenant une certaine chaîne à l'aide de dplyr

Je dois filtrer un cadre de données en utilisant comme critère les lignes contenant la chaîne RTB. J'utilise dplyr.

d.del <- df %.%
  group_by(TrackingPixel) %.%
  summarise(MonthDelivery = as.integer(sum(Revenue))) %.%
  arrange(desc(MonthDelivery))

Je sais que je peux utiliser la fonction filter dans dplyr mais je ne sais pas exactement comment lui dire de vérifier le contenu d'une chaîne.

En particulier, je souhaite vérifier le contenu de la colonne TrackingPixel. Si la chaîne contient le libellé RTB, je souhaite supprimer la ligne du résultat.

120
Gianluca

La réponse à la question avait déjà été postée par le @latemail dans les commentaires ci-dessus. Vous pouvez utiliser des expressions régulières pour le deuxième argument et les arguments suivants de filter comme ceci:

dplyr::filter(df, !grepl("RTB",TrackingPixel))

Puisque vous n'avez pas fourni les données d'origine, je vais ajouter un exemple de jouet en utilisant l'ensemble de données mtcars. Imaginez que vous ne soyez intéressé que par les voitures produites par Mazda ou Toyota.

mtcars$type <- rownames(mtcars)
dplyr::filter(mtcars, grepl('Toyota|Mazda', type))

   mpg cyl  disp  hp drat    wt  qsec vs am gear carb           type
1 21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4      Mazda RX4
2 21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4  Mazda RX4 Wag
3 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1 Toyota Corolla
4 21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1  Toyota Corona

Si vous souhaitez utiliser la méthode inverse, à savoir l'exclusion des voitures Toyota et Mazda, la commande filter ressemble à ceci:

dplyr::filter(mtcars, !grepl('Toyota|Mazda', type))
180
alex23lemm

Solution

Il est possible d'utiliser str_detect du package stringr inclus dans le package tidyverse. str_detect renvoie True ou False indiquant si le vecteur spécifié contient une chaîne spécifique. Il est possible de filtrer en utilisant cette valeur booléenne. Voir Introduction à stringr pour plus de détails sur le paquet stringr.

library(tidyverse)
# ─ Attaching packages ──────────────────── tidyverse 1.2.1 ─
# ✔ ggplot2 2.2.1     ✔ purrr   0.2.4
# ✔ tibble  1.4.2     ✔ dplyr   0.7.4
# ✔ tidyr   0.7.2     ✔ stringr 1.2.0
# ✔ readr   1.1.1     ✔ forcats 0.3.0
# ─ Conflicts ───────────────────── tidyverse_conflicts() ─
# ✖ dplyr::filter() masks stats::filter()
# ✖ dplyr::lag()    masks stats::lag()

mtcars$type <- rownames(mtcars)
mtcars %>%
  filter(str_detect(type, 'Toyota|Mazda'))
# mpg cyl  disp  hp drat    wt  qsec vs am gear carb           type
# 1 21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4      Mazda RX4
# 2 21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4  Mazda RX4 Wag
# 3 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1 Toyota Corolla
# 4 21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1  Toyota Corona

Les avantages de Stringr

Nous devrions utiliser plutôt stringr::str_detect() que base::grepl(). C'est parce qu'il y a les raisons suivantes.

  • Les fonctions fournies par le package stringr commencent par le préfixe str_, ce qui facilite la lecture du code.
  • Le premier argument des fonctions du package stringr est toujours le data.frame (ou la valeur), puis viennent les paramètres. (Merci Paolo)
object <- "stringr"
# The functions with the same prefix `str_`.
# The first argument is an object.
stringr::str_count(object) # -> 7
stringr::str_sub(object, 1, 3) # -> "str"
stringr::str_detect(object, "str") # -> TRUE
stringr::str_replace(object, "str", "") # -> "ingr"
# The function names without common points.
# The position of the argument of the object also does not match.
base::nchar(object) # -> 7
base::substr(object, 1, 3) # -> "str"
base::grepl("str", object) # -> TRUE
base::sub("str", "", object) # -> "ingr"

Référence

Les résultats du test de référence sont les suivants. str_detect est plus rapide pour les grandes trames de données.

library(rbenchmark)
library(tidyverse)

# The data. Data expo 09. ASA Statistics Computing and Graphics 
# http://stat-computing.org/dataexpo/2009/the-data.html
df <- read_csv("Downloads/2008.csv")
print(dim(df))
# [1] 7009728      29

benchmark(
  "str_detect" = {df %>% filter(str_detect(Dest, 'MCO|BWI'))},
  "grepl" = {df %>% filter(grepl('MCO|BWI', Dest))},
  replications = 10,
  columns = c("test", "replications", "elapsed", "relative", "user.self", "sys.self"))
# test replications elapsed relative user.self sys.self
# 2      grepl           10  16.480    1.513    16.195    0.248
# 1 str_detect           10  10.891    1.000     9.594    1.281
87
Keiku

Cette réponse ressemble à d’autres, mais utilise les stringr::str_detect et dplyr rownames_to_column préférés.

library(tidyverse)

mtcars %>% 
  rownames_to_column("type") %>% 
  filter(stringr::str_detect(type, 'Toyota|Mazda') )

#>             type  mpg cyl  disp  hp drat    wt  qsec vs am gear carb
#> 1      Mazda RX4 21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
#> 2  Mazda RX4 Wag 21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
#> 3 Toyota Corolla 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
#> 4  Toyota Corona 21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1

Créé le 2018-06-26 par le paquet reprex (v0.2.0).

5
Nettle

Si vous voulez trouver la chaîne dans toute colonne donnée, regardez 

Supprimer la ligne si une colonne contient une chaîne spécifique

Il s’agit essentiellement d’utiliser filter_at ou filter_all

0
Tjebo