Belirli bir dize içeren satırları filtrele


188

Bir veri çerçevesini kriter olarak dizeyi içeren bu satır kullanarak filtrelemek zorunda RTB.

Kullanıyorum dplyr.

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

Ben işlevini kullanabilirsiniz biliyorum filteriçinde dplyrama tam olarak değil bir dize içeriği kontrol edecek şekilde anlatmak için nasıl.

Özellikle sütundaki içeriği kontrol etmek istiyorum TrackingPixel. Dize etiketi içeriyorsa RTB, satırı sonuçtan kaldırmak istiyorum.


28
Hiç kullanmadım dplyr, ama yardımına baktığımda belki ?dplyr::filterböyle bir şey öneriyorum filter(df, !grepl("RTB",TrackingPixel))?
thelatemail

2
Bu aslında elde etmek istediğim şeye yakın. Tek sorun, etiketi içeren RTBve diğerlerini göstermeyen bu dizeyi korumaktır .
Gianluca

Sadece gizli bir düzenleme yaptım, şimdi !önünü ekleyerek tersine çevrildi grepl- tekrar deneyin.
thelatemail

4
Veya invertve valueparametrelerini kullanın grep. Düzenli ifadeler metinle çalışmayı bin kat daha kolay hale getirir.
Rich Scriven

4
@thelatemail greplpostgres üzerinde benim için çalışmıyor, bu MySQL için mi?
Statwonk

Yanıtlar:


257

Sorunun cevabı, @latemail tarafından yukarıdaki yorumlarda zaten gönderildi. Bunun gibi ikinci ve sonraki bağımsız değişkenler için düzenli ifadeler kullanabilirsiniz filter:

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

Orijinal verileri sağlamadığınız için, mtcarsveri kümesini kullanarak bir oyuncak örneği ekleyeceğim . Sadece Mazda veya Toyota tarafından üretilen otomobillerle ilgilendiğinizi düşünün.

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

Toyota ve Mazda arabaları hariç olmak üzere başka bir yolla yapmak istiyorsanız, filterkomut şöyle görünür:

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

sütun adı boşluk içeriyorsa. İzleme Pikselleri gibi.
MySchizoBuddy

3
istatistik paketini değil, dplyr paketinden filtre işlevini kullandığınızdan emin olun
JHowIX

2
@MySchizoBuddy: Sütun adı beyaz boşluk içeriyorsa, değişkeni ters tırnakları kullanarak seçebilirsiniz. Yukarıdaki örneği değiştirme: mtcars$`my type` <- rownames(mtcars)ve sonramtcars %>% filter(grepl('Toyota|Mazda', `my type`))
alex23lemm

13
nesne bir tbl_sqlolduğu greplzaman bunun sql'ye çevirmediğini unutmayın.
David LeBauer

seçenek 1, dplyr'ın son yüklendiğinden emin olmaktır. seçenek 2 dplyr :: filter önekidir.
userJT

157

Çözüm

Pakete dahil str_detectolan stringrambalajın kullanılması mümkündür tidyverse. str_detectdöner Trueveya Falsebelirtilen vektör bazı özel dize içeriyorsa olmadığı konusunda. Bu boole değerini kullanarak filtreleme yapmak mümkündür. Paket hakkında ayrıntılar için bkz . Stringr'e giriş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

Stringr hakkında iyi şeyler

Biz doğrusu kullanmalıdır stringr::str_detect()daha base::grepl(). Bunun nedeni aşağıdaki nedenler olmasıdır.

  • stringrPaket tarafından sağlanan işlevler str_, kodun okunmasını kolaylaştıran önekle başlar .
  • stringrPaket işlevlerinin ilk argümanı her zaman data.frame'dir (veya değer), sonra parametreler gelir. (Teşekkürler 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"

Karşılaştırma

Kıyaslama testinin sonuçları aşağıdaki gibidir. Büyük veri çerçevesi str_detectiçin daha hızlıdır.

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

1
Stringr neden grep 'den daha iyi bir seçenek?
CameronNemo

2
@CameronNemo stringrPaket tarafından sağlanan işlevler , kodun okunmasını kolaylaştıran str_ önekiyle başlar. Son zamanlarda modern R kodunda stringr kullanılması tavsiye edilir.
Keiku

3
Bunun çok kişisel bir tercih olduğunu düşünüyorum ve @CameronNemo ile base Raynı derecede iyi olduğunu kabul ediyorum stringr. Bize kıyaslama gibi bazı 'sert gerçekler' sağlar ve sadece "tavsiye edilir" i (kim tavsiye eder?) Belirtmekle kalmazsanız, bu çok takdir edilecektir. Teşekkürler
Tjebo

2
Diğer bir neden, düzenli çerçevedeki tutarlılıktır: bir işlevin ilk argümanı her zaman data.frame'dir (veya değerdir), sonra parametreler gelir.
Paolo

22

Bu cevap diğerlerine benzer, ancak tercih edilen stringr::str_detectve dplyr kullanarak 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

2018-06-26 tarihinde reprex paketi (v0.2.0) tarafından oluşturuldu .


1
str_detectolduğu stringrpaket
jsta

4

düzenle yeni across()sözdizimini içeriyor

İşte veya daha önce tidyversekullanan başka bir çözüm . Avantajı, birden fazla sütuna kolayca genişletebilmenizdir .filter(across())filter_at

Aşağıda , "V" dizesini aramak için, dizeyi herhangi bir sütundaki filter_allbulmak için bir çözümdiamonds

library(tidyverse)

Yalnızca bir sütunda dize

# for only one column... extendable to more than one creating a column list in `across` or `vars`!
mtcars %>% 
  rownames_to_column("type") %>% 
  filter(across(type, ~ !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

Aynı şey için artık geçerli olan söz dizimi şöyle olacaktır:

mtcars %>% 
  rownames_to_column("type") %>% 
  filter_at(.vars= vars(type), all_vars(!grepl('Toyota|Mazda',.))) 

Tüm sütunlarda dize:

# remove all rows where any column contains 'V'
diamonds %>%
  filter(across(everything(), ~ !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

Aynı şey için artık geçerli olan söz dizimi şöyle olacaktır:

diamonds %>% 
  filter_all(all_vars(!grepl('V', .))) %>%
  head

Aşağıdakiler için farklı bir alternatif bulmaya çalıştım, ancak hemen iyi bir çözüm bulamadım:

    #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

Güncelleme: Bu cevaptaki Petr Kajzar kullanıcısı sayesinde , yukarıdakiler için de bir yaklaşım:

diamonds %>%
   filter(rowSums(across(everything(), ~grepl("V", .x))) > 0)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.