[r] 특정 문자열을 포함하는 행 필터링

문자열이 포함 된 행을 기준으로 사용하여 데이터 프레임을 필터링해야합니다 RTB.

을 사용하고 dplyr있습니다.

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

함수 filter를 사용할 수 있다는 것을 알고 dplyr있지만 문자열의 내용을 확인하도록 알려주는 방법을 정확히 알지 못합니다.

특히 열의 내용을 확인하고 싶습니다 TrackingPixel. 문자열에 레이블이 포함되어 있으면 RTB결과에서 행을 제거하고 싶습니다.



답변

질문에 대한 답변은 이미 @latemail에 의해 위의 의견에 게시되었습니다. 다음과 filter같은 두 번째 및 후속 인수에 정규식을 사용할 수 있습니다 .

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

원본 데이터를 제공하지 않았으므로 mtcars데이터 세트 를 사용하여 장난감 예제를 추가합니다 . Mazda 또는 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

Toyota와 Mazda 자동차를 제외하고 다른 방법으로 원한다면 filter명령은 다음과 같습니다.

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


답변

해결책

사용할 수 str_detectstringr에 포함 패키지 tidyverse패키지. str_detect반환 True또는 False지정된 벡터 일부 특정 문자열을 포함하는지에. 이 부울 값을 사용하여 필터링 할 수 있습니다. 패키지에 대한 자세한 내용은 스트링거 소개를 참조하십시오 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에 대한 좋은 점

우리는 오히려 사용해야합니다 stringr::str_detect()보다 base::grepl(). 다음과 같은 이유가 있기 때문입니다.

  • stringr패키지에서 제공하는 함수 는 prefix str_를 사용하여 코드를보다 쉽게 ​​읽을 수있게합니다.
  • stringrpackage 함수의 첫 번째 인수 는 항상 data.frame (또는 value)이며 매개 변수가옵니다. (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"

기준

벤치 마크 테스트 결과는 다음과 같습니다. 큰 데이터 프레임의 경우 str_detect더 빠릅니다.

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


답변

이것은 다른 것과 비슷하지만 preferred stringr::str_detect및 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

reprex 패키지 (v0.2.0)로 2018-06-26에 작성되었습니다 .


답변

최신 across()구문이 포함 된 편집

다음은 또는 previous를 tidyverse사용하는 다른 솔루션 입니다. 장점은 둘 이상의 열로 쉽게 확장 할 수 있다는 것 입니다.filter(across())filter_at

와 솔루션도 아래 filter_all에서 문자열 찾기 위해 어떤 사용하여 열을 diamonds문자열 “V”를 찾고, 예를 들어

library(tidyverse)

하나의 열에 만있는 문자열

# 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

현재 대체 된 구문은 다음과 같습니다.

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

모든 열의 문자열 :

# 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

현재 대체 된 구문은 다음과 같습니다.

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

나는 다음에 대한 대안을 찾으려고했지만 즉시 좋은 해결책을 찾지 못했습니다.

    #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

업데이트 : 이 답변의 사용자 Petr Kajzar에게 감사드립니다 .

diamonds %>%
   filter(rowSums(across(everything(), ~grepl("V", .x))) > 0)


답변