उन पंक्तियों को फ़िल्टर करें जिनमें एक निश्चित स्ट्रिंग होती है


188

मुझे एक डेटा फ्रेम को कसौटी के रूप में उपयोग करना होगा जिसमें उन पंक्तियों को शामिल किया गया है जिसमें स्ट्रिंग शामिल है RTB

मैं उपयोग कर रहा हूं dplyr

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

मुझे पता है कि मैं फ़ंक्शन का उपयोग कर सकता हूं filter, dplyrलेकिन मैं इसे स्ट्रिंग की सामग्री की जांच करने के लिए बिल्कुल नहीं बताऊंगा।

विशेष रूप से मैं कॉलम में सामग्री की जांच करना चाहता हूं TrackingPixel। यदि स्ट्रिंग में वह लेबल है जिसमें RTBमैं परिणाम से पंक्ति को हटाना चाहता हूं।


28
मैंने कभी उपयोग नहीं किया है dplyr, लेकिन ?dplyr::filterमैं filter(df, !grepl("RTB",TrackingPixel))शायद मदद की तरह कुछ देख रहा हूँ ?
thelatemail

2
यह वास्तव में वही है जो मैं हासिल करना चाहता हूं। एकमात्र मुद्दा यह है कि उन स्ट्रिंग को बनाए रखा जा रहा है जिसमें लेबल शामिल है RTBऔर दूसरों को नहीं दिखा रहा है।
गियानलुका

मैं बस एक चुपके संपादित में डाल दिया, कि अब !सामने जोड़कर उलट दिया गया है grepl- इसे फिर से प्रयास करें।
Thelatemail

4
या का उपयोग invertऔर valueके तर्कों grep। नियमित अभिव्यक्ति पाठ के साथ एक हजार गुना आसान काम करती है।
रिच स्क्रीवन

4
@thelatemail greplमेरे लिए पोस्टग्रेज पर काम नहीं करता है, क्या यह MySQL के लिए है?
स्टैटवॉन्क

जवाबों:


257

प्रश्न का उत्तर पहले से ही ऊपर टिप्पणियों में @latemail द्वारा पोस्ट किया गया था। आप filterइस तरह के दूसरे और बाद के तर्कों के लिए नियमित अभिव्यक्ति का उपयोग कर सकते हैं :

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

चूंकि आपने मूल डेटा प्रदान नहीं किया है, इसलिए मैं mtcarsडेटा सेट का उपयोग करके एक खिलौना उदाहरण जोड़ूंगा । कल्पना कीजिए कि आप केवल मज़्दा या टोयोटा द्वारा निर्मित कारों में रुचि रखते हैं।

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

यदि आप इसे दूसरे तरीके से करना चाहते हैं, अर्थात् टोयोटा और मज़्दा कारों को छोड़कर, filterकमांड इस तरह दिखता है:

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

क्या होगा अगर कॉलम नाम में एक स्थान है। ट्रैकिंग पिक्सेल की तरह।
MySchizoBuddy

3
सुनिश्चित करें कि आप dplyr पैकेज से फ़िल्टर फ़ंक्शन का उपयोग कर रहे हैं, न कि आँकड़े पैकेज
JHowIX

2
@MySchizoBuddy: यदि कॉलम नाम में सफेद स्थान है, तो आप बैकटिक्स का उपयोग करके चर का चयन कर सकते हैं। ऊपर दिए गए उदाहरण को संशोधित करते हुए: mtcars$`my type` <- rownames(mtcars)और फिरmtcars %>% filter(grepl('Toyota|Mazda', `my type`))
alex23lemm

13
ध्यान दें कि यह तब काम नहीं करता है जब ऑब्जेक्ट एक है tbl_sqlजैसा greplकि sql में अनुवाद नहीं करता है।
डेविड लेबॉउर

विकल्प 1 यह सुनिश्चित करने के लिए जाना जाता है कि अंतिम रूप से लोड किया गया। विकल्प 2 आप उपसर्ग dplyr है :: फ़िल्टर।
userJT

157

उपाय

यह उपयोग करना संभव है str_detectकी stringrपैकेज में शामिल 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::str_detect()की तुलना में base::grepl()। इसका कारण यह है कि निम्नलिखित कारण हैं।

  • stringrपैकेज द्वारा प्रदान किए गए कार्य उपसर्ग के साथ शुरू होते हैं str_, जिससे कोड को पढ़ना आसान हो जाता है।
  • stringrपैकेज के कार्यों का पहला तर्क हमेशा data.frame (या मूल्य) होता है, फिर पैरामीटर आता है। (धन्यवाद पाओलो)
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

1
Grep से बेहतर विकल्प स्ट्रिंग क्यों है?
कैमरूननेमो

2
@CameronNemo stringrपैकेज द्वारा प्रदान किए गए फ़ंक्शंस उपसर्ग str_ से शुरू होते हैं, जो कोड को पढ़ना आसान बनाता है। हाल के आधुनिक आर कोड में, स्ट्रिंग का उपयोग करने की सिफारिश की गई है।
कीकू

3
मुझे लगता है कि यह एक बहुत ही व्यक्तिगत प्राथमिकता है और मैं @CameronNemo से सहमत हूं जो base Rउतना ही अच्छा है stringr। यदि आप हमें बेंचमार्किंग जैसे कुछ 'कठिन तथ्यों' के साथ प्रदान करते हैं, और न केवल "यह अनुशंसित है" (जो यह अनुशंसा करता है?) बताते हुए, यह बहुत सराहना की जाएगी। धन्यवाद
Tjebo

2
एक अन्य कारण tidyverse ढांचे में स्थिरता है: किसी फ़ंक्शन का पहला तर्क हमेशा data.frame (या मान) होता है, फिर पैरामीटर आता है।
पाओलो

22

यह दूसरों के समान उत्तर देता है, लेकिन पसंदीदा stringr::str_detectऔर सपने देखने का उपयोग करता है 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 को रेप्रेक्स पैकेज ( v0.2.0 ) द्वारा बनाया गया ।


1
str_detectमें है stringrपैकेज
jsta

4

नए across()सिंटैक्स को संपादित करना शामिल है

यहाँ एक और tidyverseउपाय है, उपयोग filter(across())या पहले का filter_at। लाभ यह है कि आप आसानी से एक से अधिक कॉलम तक बढ़ा सकते हैं ।

नीचे भी किसी भी कॉलम filter_allमें स्ट्रिंग को खोजने के लिए एक समाधान के साथ , उदाहरण के लिए, स्ट्रिंग "वी" की तलाश में।diamonds

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

अपडेट: इस उत्तर में उपयोगकर्ता पेट्र काजर के लिए धन्यवाद , यहां भी उपरोक्त के लिए एक दृष्टिकोण है:

diamonds %>%
   filter(rowSums(across(everything(), ~grepl("V", .x))) > 0)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.