Filtern Sie Zeilen, die eine bestimmte Zeichenfolge enthalten

187

Ich muss einen Datenrahmen anhand der Zeile filtern, in der die Zeichenfolge enthalten ist RTB.

Ich benutze dplyr.

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

Ich weiß, dass ich die Funktion filterin verwenden kann, dplyraber ich weiß nicht genau, wie ich sie anweisen soll, nach dem Inhalt einer Zeichenfolge zu suchen.

Insbesondere möchte ich den Inhalt in der Spalte überprüfen TrackingPixel. Wenn die Zeichenfolge die Bezeichnung enthält, RTBmöchte ich die Zeile aus dem Ergebnis entfernen.

Gianluca
quelle
27
Ich habe noch nie benutzt dplyr, aber wenn ?dplyr::filterich mir die Hilfe in anschaue, würde ich so etwas wie filter(df, !grepl("RTB",TrackingPixel))vielleicht vorschlagen ?
E-Mail
1
Dies ist eigentlich nahe an dem, was ich erreichen möchte. Das einzige Problem besteht darin, die Zeichenfolge beizubehalten, die die Bezeichnung enthält, RTBund die anderen nicht anzuzeigen.
Gianluca
Ich habe gerade eine Stealth-Bearbeitung vorgenommen, die jetzt durch Hinzufügen der !vor grepl- wieder umgekehrt wird .
E-Mail
4
Oder verwenden Sie die invertund valueArgumente von grep. Reguläre Ausdrücke erleichtern die Arbeit mit Text tausendmal.
Rich Scriven
4
@thelatemail greplfunktioniert bei mir nicht mit Postgres, ist das für MySQL?
Statwonk

Antworten:

254

Die Antwort auf die Frage wurde bereits von der @latemail in den obigen Kommentaren gepostet. Sie können reguläre Ausdrücke für das zweite und nachfolgende Argument filterwie folgt verwenden:

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

Da Sie die Originaldaten nicht angegeben haben, werde ich anhand des mtcarsDatensatzes ein Spielzeugbeispiel hinzufügen . Stellen Sie sich vor, Sie interessieren sich nur für Autos von Mazda oder 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

Wenn Sie es umgekehrt machen möchten, nämlich ohne Toyota und Mazda, filtersieht der Befehl folgendermaßen aus:

dplyr::filter(mtcars, !grepl('Toyota|Mazda', type))
alex23lemm
quelle
Was ist, wenn der Spaltenname ein Leerzeichen enthält? wie Tracking-Pixel.
MySchizoBuddy
3
Stellen Sie sicher, dass Sie die Filterfunktion aus dem Paket dplyr verwenden, nicht aus dem Paket stats
JHowIX
2
@MySchizoBuddy: Wenn der Spaltenname Leerzeichen enthält, können Sie die Variable mithilfe von Backticks auswählen. Ändern Sie das obige Beispiel: mtcars$`my type` <- rownames(mtcars)und dannmtcars %>% filter(grepl('Toyota|Mazda', `my type`))
alex23lemm
13
Beachten Sie, dass dies nicht funktioniert, wenn das Objekt ein tbl_sqlas ist, grepldas nicht in SQL übersetzt wird.
David LeBauer
Option 1 ist, sicher zu wissen, dass dplyr zuletzt geladen wurde. Option 2 ist das Präfix dplyr :: filter.
userJT
156

Lösung

Es ist möglich, str_detectdas im stringrPaket enthaltene tidyversePaket zu verwenden. str_detectgibt zurück Trueoder Falseob der angegebene Vektor eine bestimmte Zeichenfolge enthält. Es ist möglich, mit diesem booleschen Wert zu filtern. Weitere Informationen zum stringrPaket finden Sie unter Einführung in 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

Die guten Dinge über Stringr

Wir sollten eher verwenden stringr::str_detect()als base::grepl(). Dies liegt daran, dass es folgende Gründe gibt.

  • Die vom stringrPaket bereitgestellten Funktionen beginnen mit dem Präfix str_, wodurch der Code leichter lesbar wird.
  • Das erste Argument der Funktionen des stringrPakets ist immer der data.frame (oder Wert), dann kommen die Parameter. (Danke 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"

Benchmark

Die Ergebnisse des Benchmark-Tests sind wie folgt. Für große Datenrahmen str_detectist schneller.

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
Keiku
quelle
1
Warum ist stringr eine bessere Option als grep?
CameronNemo
2
@CameronNemo Die vom stringrPaket bereitgestellten Funktionen beginnen mit dem Präfix str_, wodurch der Code leichter zu lesen ist. In neuerem modernen R-Code wird empfohlen, stringr zu verwenden.
Keiku
3
Ich denke, dies ist eine sehr persönliche Präferenz und ich stimme @CameronNemo zu, base Rdas so gut ist wie stringr. Wenn Sie uns einige „harte Fakten“ wie Benchmarking liefern und nicht nur "es wird empfohlen" angeben (wer empfiehlt es?), Wäre dies sehr dankbar. Vielen Dank
Tjebo
2
Ein weiterer Grund ist die Konsistenz im Tidyverse-Framework: Das erste Argument einer Funktion ist immer der data.frame (oder Wert), dann kommen die Parameter.
Paolo
22

Diese Antwort ähnelt anderen, verwendet jedoch bevorzugt stringr::str_detectund dplyr rownames_to_column.

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

Erstellt am 26.06.2018 vom reprex-Paket (v0.2.0).

Nessel
quelle
1
str_detectist im stringrPaket
jsta
3

Hier ist eine andere tidyverseLösung mit filter_at. Der Vorteil ist, dass Sie problemlos auf mehr als eine Spalte erweitern können. Unten auch eine Lösung mit filter_all, um die Zeichenfolge in einer beliebigen Spalte zu finden, am diamondsBeispiel der Suche nach der Zeichenfolge "V"

library(tidyverse)

# for only one column... extendable to more than one creating a column list in `vars`!
mtcars %>% 
  rownames_to_column("type") %>% 
  filter_at(.vars= vars(type), all_vars(!grepl('Toyota|Mazda',.))) %>%
  head()
#>                type  mpg cyl  disp  hp drat    wt  qsec vs am gear carb
#> 1        Datsun 710 22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
#> 2    Hornet 4 Drive 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
#> 3 Hornet Sportabout 18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
#> 4           Valiant 18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
#> 5        Duster 360 14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
#> 6         Merc 240D 24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
```

Zeichenfolge in einer beliebigen Spalte : verwendenfilter_all

#remove all rows where any column contains 'V'
    diamonds %>% 
      filter_all(all_vars(!grepl('V',.))) %>%
      head
    #> # A tibble: 6 x 10
    #>   carat cut     color clarity depth table price     x     y     z
    #>   <dbl> <ord>   <ord> <ord>   <dbl> <dbl> <int> <dbl> <dbl> <dbl>
    #> 1  0.23 Ideal   E     SI2      61.5    55   326  3.95  3.98  2.43
    #> 2  0.21 Premium E     SI1      59.8    61   326  3.89  3.84  2.31
    #> 3  0.31 Good    J     SI2      63.3    58   335  4.34  4.35  2.75
    #> 4  0.3  Good    J     SI1      64      55   339  4.25  4.28  2.73
    #> 5  0.22 Premium F     SI1      60.4    61   342  3.88  3.84  2.33
    #> 6  0.31 Ideal   J     SI2      62.2    54   344  4.35  4.37  2.71
    #get all rows where any column contains 'V'
    diamonds %>%
    filter_all(any_vars(grepl('V',.))) %>%
      head
    #> # A tibble: 6 x 10
    #>   carat cut       color clarity depth table price     x     y     z
    #>   <dbl> <ord>     <ord> <ord>   <dbl> <dbl> <int> <dbl> <dbl> <dbl>
    #> 1 0.23  Good      E     VS1      56.9    65   327  4.05  4.07  2.31
    #> 2 0.290 Premium   I     VS2      62.4    58   334  4.2   4.23  2.63
    #> 3 0.24  Very Good J     VVS2     62.8    57   336  3.94  3.96  2.48
    #> 4 0.24  Very Good I     VVS1     62.3    57   336  3.95  3.98  2.47
    #> 5 0.26  Very Good H     SI1      61.9    55   337  4.07  4.11  2.53
    #> 6 0.22  Fair      E     VS2      65.1    61   337  3.87  3.78  2.49

<sup>Created on 2020-04-01 by the [reprex package](https://reprex.tidyverse.org) (v0.3.0)</sup>
Tjebo
quelle