數據處理第3部分:選擇行的基本和高級的方法

原文地址:https://suzan.rbind.io/2018/02/dplyr-tutorial-3/ 作者:Suzan Baert 這是系列dplyr系列教程中的第三篇博客文章。 在這篇文章中,我們將介紹如何挑選您的數據。 除了filter的基礎知識外,它還介紹了一些更好的方法,用near()between()挑選數字列,或用正則表達式過濾字符串列。


The data 根據之前的博客文章,爲了方便人們複製粘貼代碼和實驗,我使用的是內置數據集。 此數據集內置於ggplot2中,因此如果您加載tidyverse,您將獲得它。 否則,只需添加一次msleep < - ggplot2 :: msleep參數即可獲得數據集。

library(dplyr)
library(stringr)
msleep <- ggplot2::msleep

glimpse(msleep)

## Observations: 83
## Variables: 11
## $ name         <chr> "Cheetah", "Owl monkey", "Mountain beaver", "Grea...
## $ genus        <chr> "Acinonyx", "Aotus", "Aplodontia", "Blarina", "Bo...
## $ vore         <chr> "carni", "omni", "herbi", "omni", "herbi", "herbi...
## $ order        <chr> "Carnivora", "Primates", "Rodentia", "Soricomorph...
## $ conservation <chr> "lc", NA, "nt", "lc", "domesticated", NA, "vu", N...
## $ sleep_total  <dbl> 12.1, 17.0, 14.4, 14.9, 4.0, 14.4, 8.7, 7.0, 10.1...
## $ sleep_rem    <dbl> NA, 1.8, 2.4, 2.3, 0.7, 2.2, 1.4, NA, 2.9, NA, 0....
## $ sleep_cycle  <dbl> NA, NA, NA, 0.1333333, 0.6666667, 0.7666667, 0.38...
## $ awake        <dbl> 11.9, 7.0, 9.6, 9.1, 20.0, 9.6, 15.3, 17.0, 13.9,...
## $ brainwt      <dbl> NA, 0.01550, NA, 0.00029, 0.42300, NA, NA, NA, 0....
## $ bodywt       <dbl> 50.000, 0.480, 1.350, 0.019, 600.000, 3.850, 20.4...

Basic row filters

在許多情況下,您不希望在分析中包括所有行,而只包括選擇的行。 僅使用特定行的函數在dplyr中稱爲“filter()”。 過濾器的一般語法是:filter(dataset,condition)。 如果您在管道內部進行過濾,則只會在數據集通過管道輸入函數時看到條件參數。

Filtering rows based on a numeric variable

You can filter numeric variables based on their values. The most used operators for this are >, >=, <, <=, == and !=.

msleep %>% 
  select(name, sleep_total) %>% 
  filter(sleep_total > 18)

## # A tibble: 4 x 2
##   name                 sleep_total
##   <chr>                      <dbl>
## 1 Big brown bat               19.7
## 2 Thick-tailed opposum        19.4
## 3 Little brown bat            19.9
## 4 Giant armadillo             18.1

如果要選擇一系列值,可以使用兩個邏輯要求。 例如,爲了選擇總休眠時間在15到18小時之間的所有動物,我可以使用:filter(sleep_total> = 16,sleep_total <= 18),但使用between()稍微短一些

msleep %>% 
  select(name, sleep_total) %>% 
  filter(between(sleep_total, 16, 18))

## # A tibble: 4 x 2
##   name                   sleep_total
##   <chr>                        <dbl>
## 1 Owl monkey                    17.0
## 2 Long-nosed armadillo          17.4
## 3 North American Opossum        18.0
## 4 Arctic ground squirrel        16.6

可以派上用場的另一個函數是near(),它將選擇幾乎給定值的所有代碼。 您必須指定容差“tol”以指示值可以達到多遠。 你可以添加一個特定的數字:filter(near(sleep_total,17,tol = 0.5))例如將返回sleep_total在16.5和17.5之間的任何行,或者你可以添加一個公式。 示例代碼將返回一個標準差爲17的所有行。

msleep %>% 
  select(name, sleep_total) %>% 
  filter(near(sleep_total, 17, tol = sd(sleep_total)))

## # A tibble: 26 x 2
##    name                       sleep_total
##    <chr>                            <dbl>
##  1 Owl monkey                        17.0
##  2 Mountain beaver                   14.4
##  3 Greater short-tailed shrew        14.9
##  4 Three-toed sloth                  14.4
##  5 Long-nosed armadillo              17.4
##  6 North American Opossum            18.0
##  7 Big brown bat                     19.7
##  8 Western american chipmunk         14.9
##  9 Thick-tailed opposum              19.4
## 10 Mongolian gerbil                  14.2
## # ... with 16 more rows

Filtering based on a exact character variable matches

例如,如果要選擇特定的動物組,可以使用==比較運算符:

msleep %>% 
  select(order, name, sleep_total) %>% 
  filter(order == "Didelphimorphia")

## # A tibble: 2 x 3
##   order           name                   sleep_total
##   <chr>           <chr>                        <dbl>
## 1 Didelphimorphia North American Opossum        18.0
## 2 Didelphimorphia Thick-tailed opposum          19.4

同樣,您可以使用其他運算符:

*filter(order!=“Rodentia”)將選擇除Rodentia行之外的所有內容。

*filter(name>“v”)只會在字母v之後選擇字母中帶有名稱的行。

如果要選擇多個動物,可以使用%in%運算符。 以下代碼將僅選擇具有屬於Didelphimorphia和Diprotodontia順序的動物的行。

msleep %>% 
  select(order, name, sleep_total) %>% 
  filter(order %in% c("Didelphimorphia", "Diprotodontia"))

## # A tibble: 4 x 3
##   order           name                   sleep_total
##   <chr>           <chr>                        <dbl>
## 1 Didelphimorphia North American Opossum        18.0
## 2 Didelphimorphia Thick-tailed opposum          19.4
## 3 Diprotodontia   Phalanger                     13.7
## 4 Diprotodontia   Potoroo                       11.1

您可以使用%in%運算符來取消選擇某些組,在這種情況下,您必須通過在filter的開頭添加感嘆號來否定。 製作!%in%似乎是邏輯但它不起作用。

remove <- c("Rodentia", "Carnivora", "Primates")
msleep %>% 
  select(order, name, sleep_total) %>% 
  filter(!order %in% remove)

## # A tibble: 37 x 3
##    order           name                       sleep_total
##    <chr>           <chr>                            <dbl>
##  1 Soricomorpha    Greater short-tailed shrew       14.9 
##  2 Artiodactyla    Cow                               4.00
##  3 Pilosa          Three-toed sloth                 14.4 
##  4 Artiodactyla    Roe deer                          3.00
##  5 Artiodactyla    Goat                              5.30
##  6 Soricomorpha    Star-nosed mole                  10.3 
##  7 Soricomorpha    Lesser short-tailed shrew         9.10
##  8 Cingulata       Long-nosed armadillo             17.4 
##  9 Hyracoidea      Tree hyrax                        5.30
## 10 Didelphimorphia North American Opossum           18.0 
## # ... with 27 more rows

根據正則表達式過濾行

只有在您可以使用完整變量內容時,上述選項纔有效。 在某些情況下,雖然需要根據部分匹配進行過濾。 在這種情況下,我們需要一個函數來評估字符串上的正則表達式並返回布爾值。 每當語句爲“TRUE”時,該行將被過濾。 這有兩個主要選項:base R的grepl()函數,或stringr包中的str_detect()

無論何時尋找部分匹配,重要的是要記住R是區分大小寫的。 通過使用filter(str_detect(name,pattern =“mouse”))我們將遺漏任何名爲Mouse的行。 在這種情況下,它沒有什麼區別,但它是一個很好的習慣創建。

我在下面使用了'str_detect(),因爲它更容易理解。 對於那些感興趣的人,替代方案是:filter(grepl(pattern =“mouse”,tolower(name)))`。

msleep %>% 
  select(name, sleep_total) %>% 
  filter(str_detect(tolower(name), pattern = "mouse"))

## # A tibble: 5 x 2
##   name                       sleep_total
##   <chr>                            <dbl>
## 1 Vesper mouse                      7.00
## 2 House mouse                      12.5 
## 3 Northern grasshopper mouse       14.5 
## 4 Deer mouse                       11.5 
## 5 African striped mouse             8.70

基於多種條件的過濾

以上示例基於單個條件返回行,但filter選項還允許AND和OR樣式過濾器:

*filter(condition1,condition2)將返回滿足兩個條件的行。

*filter(condition1,!condition2)將返回條件1爲真但條件2不爲的所有行。

*filter(condition1 | condition2)將返回滿足條件1和/或條件2的行。

*filter(xor(condition1,condition2)將返回只滿足其中一個條件的所有行,而不是滿足兩個條件時。

可以組合多個AND,OR和NOT條件。 示例代碼將返回bodywt大於100的所有行,並且sleep_total大於15或者不是Carnivora訂單的一部分。

msleep %>% 
  select(name, order, sleep_total:bodywt) %>% 
  filter(bodywt > 100, (sleep_total > 15 | order != "Carnivora"))

## # A tibble: 10 x 8
##    name      order  sleep_total sleep_rem sleep_cycle awake brainwt bodywt
##    <chr>     <chr>        <dbl>     <dbl>       <dbl> <dbl>   <dbl>  <dbl>
##  1 Cow       Artio~        4.00     0.700       0.667 20.0    0.423    600
##  2 Asian el~ Probo~        3.90    NA          NA     20.1    4.60    2547
##  3 Horse     Peris~        2.90     0.600       1.00  21.1    0.655    521
##  4 Donkey    Peris~        3.10     0.400      NA     20.9    0.419    187
##  5 Giraffe   Artio~        1.90     0.400      NA     22.1   NA        900
##  6 Pilot wh~ Cetac~        2.70     0.100      NA     21.4   NA        800
##  7 African ~ Probo~        3.30    NA          NA     20.7    5.71    6654
##  8 Tiger     Carni~       15.8     NA          NA      8.20  NA        163
##  9 Brazilia~ Peris~        4.40     1.00        0.900 19.6    0.169    208
## 10 Bottle-n~ Cetac~        5.20    NA          NA     18.8   NA        173

Example with xor()

msleep %>%
  select(name, bodywt:brainwt) %>% 
  filter(xor(bodywt > 100, brainwt > 1))

## # A tibble: 5 x 3
##   name            bodywt brainwt
##   <chr>            <dbl>   <dbl>
## 1 Cow              600     0.423
## 2 Horse            521     0.655
## 3 Donkey           187     0.419
## 4 Human             62.0   1.32 
## 5 Brazilian tapir  208     0.169

Example with !: The sample code will select all rows where brainwt is larger than 1, but bodywt does not exceed 100.

msleep %>% 
  select(name, sleep_total, brainwt, bodywt) %>% 
  filter(brainwt > 1, !bodywt > 100)

## # A tibble: 1 x 4
##   name  sleep_total brainwt bodywt
##   <chr>       <dbl>   <dbl>  <dbl>
## 1 Human        8.00    1.32   62.0

過濾掉空行

要過濾掉空行,你可以否定過濾器中的is.na()函數: 示例代碼將刪除conservationNA的所有行。

msleep %>% 
  select(name, conservation:sleep_cycle) %>% 
  filter(!is.na(conservation))

## # A tibble: 54 x 5
##    name                     conservation sleep_total sleep_rem sleep_cycle
##    <chr>                    <chr>              <dbl>     <dbl>       <dbl>
##  1 Cheetah                  lc                 12.1     NA          NA    
##  2 Mountain beaver          nt                 14.4      2.40       NA    
##  3 Greater short-tailed sh~ lc                 14.9      2.30        0.133
##  4 Cow                      domesticated        4.00     0.700       0.667
##  5 Northern fur seal        vu                  8.70     1.40        0.383
##  6 Dog                      domesticated       10.1      2.90        0.333
##  7 Roe deer                 lc                  3.00    NA          NA    
##  8 Goat                     lc                  5.30     0.600      NA    
##  9 Guinea pig               domesticated        9.40     0.800       0.217
## 10 Grivet                   lc                 10.0      0.700      NA    
## # ... with 44 more rows

Filtering across multiple columns

dplyr包有一些強大的變體可以一次過濾多個列:

*filter_all()將根據您的進一步說明過濾所有列 *filter_if()需要一個返回布爾值的函數來指示要過濾的列。如果是這樣,那麼將對這些列執行過濾器指令。 *filter_at()要求你在vars()參數中指定要進行過濾的列。

在這些情況下,有一般語法:首先指定哪些列,然後提及過濾器的條件。在許多情況下,您需要一個.運算符,該運算符指的是我們正在查看的值。

過濾所有

不可否認,msleep並不是展示這種能力的最佳數據庫,但想象一下,你有一個包含幾列的數據庫,並且你想要選擇在任一列中都有某個單詞的所有行。以一個財務數據框爲例,你想要選擇帶有'food'的所有行,是否在主類別欄,子類別欄,評論欄或你花費的地方提到了食物。 您可以在OR語句中包含4個不同條件的長過濾器語句。或者您只是過濾所有列的字符串“food”。

在下面的示例代碼中,我在所有列中搜索字符串“Ca”。我想保留在任何變量中出現字符串“Ca”的行,所以我將條件包裝在any_vars()中。 下面的代碼基本上要求保留任何變量中包含模式“Ca”的行。

msleep %>% 
  select(name:order, sleep_total, -vore) %>% 
  filter_all(any_vars(str_detect(., pattern = "Ca")))

## # A tibble: 16 x 4
##    name              genus        order        sleep_total
##    <chr>             <chr>        <chr>              <dbl>
##  1 Cheetah           Acinonyx     Carnivora          12.1 
##  2 Northern fur seal Callorhinus  Carnivora           8.70
##  3 Vesper mouse      Calomys      Rodentia            7.00
##  4 Dog               Canis        Carnivora          10.1 
##  5 Roe deer          Capreolus    Artiodactyla        3.00
##  6 Goat              Capri        Artiodactyla        5.30
##  7 Guinea pig        Cavis        Rodentia            9.40
##  8 Domestic cat      Felis        Carnivora          12.5 
##  9 Gray seal         Haliochoerus Carnivora           6.20
## 10 Tiger             Panthera     Carnivora          15.8 
## 11 Jaguar            Panthera     Carnivora          10.4 
## 12 Lion              Panthera     Carnivora          13.5 
## 13 Caspian seal      Phoca        Carnivora           3.50
## 14 Genet             Genetta      Carnivora           6.30
## 15 Arctic fox        Vulpes       Carnivora          12.5 
## 16 Red fox           Vulpes       Carnivora           9.80

對於數值值也可以這樣做:此代碼將保留任何值低於0.1的行:

msleep %>%  
  select(name, sleep_total:bodywt) %>% 
  filter_all(any_vars(. < 0.1))

## # A tibble: 47 x 7
##    name           sleep_total sleep_rem sleep_cycle awake  brainwt  bodywt
##    <chr>                <dbl>     <dbl>       <dbl> <dbl>    <dbl>   <dbl>
##  1 Owl monkey           17.0      1.80       NA      7.00  1.55e-2 4.80e-1
##  2 Greater short~       14.9      2.30        0.133  9.10  2.90e-4 1.90e-2
##  3 Vesper mouse          7.00    NA          NA     17.0  NA       4.50e-2
##  4 Dog                  10.1      2.90        0.333 13.9   7.00e-2 1.40e+1
##  5 Roe deer              3.00    NA          NA     21.0   9.82e-2 1.48e+1
##  6 Guinea pig            9.40     0.800       0.217 14.6   5.50e-3 7.28e-1
##  7 Chinchilla           12.5      1.50        0.117 11.5   6.40e-3 4.20e-1
##  8 Star-nosed mo~       10.3      2.20       NA     13.7   1.00e-3 6.00e-2
##  9 African giant~        8.30     2.00       NA     15.7   6.60e-3 1.00e+0
## 10 Lesser short-~        9.10     1.40        0.150 14.9   1.40e-4 5.00e-3
## # ... with 37 more rows

any_vars()語句等價於OR,所以當然還有AND語句的等價句:all_vars()。 以下代碼將保留所有值均高於1的所有行。

msleep %>%  
  select(name, sleep_total:bodywt, -awake) %>% 
  filter_all(all_vars(. > 1))

## # A tibble: 1 x 6
##   name  sleep_total sleep_rem sleep_cycle brainwt bodywt
##   <chr>       <dbl>     <dbl>       <dbl>   <dbl>  <dbl>
## 1 Human        8.00      1.90        1.50    1.32   62.0

Filter if

filter_all()函數有時會有點瘋狂。 msleep數據集有一組睡眠和體重測量,其中一些數據丟失 - 我無法在那裏添加數據。 但是前幾組專欄只包含動物信息。 Vesper Mouse的遺體缺失,但這是我仍然可以挖掘並添加到數據框的信息,如果我想要的話。 所以想象一下,我想找出前幾列中我們NA的所有數據行。 filter_all(any_vars(is.na(。)))將是非常無用的,因爲它將返回27行,其中許多是測量部分中缺少的數據。

在這種情況下:filter_if()派上用場。 描述列都是字符列,而測量數據是數字。 所以使用filter_if()我可以指定我只想過濾字符變量。 在這種情況下,我只得到7行。

msleep %>% 
  select(name:order, sleep_total:sleep_rem) %>% 
  filter_if(is.character, any_vars(is.na(.)))

## # A tibble: 7 x 6
##   name            genus       vore  order          sleep_total sleep_rem
##   <chr>           <chr>       <chr> <chr>                <dbl>     <dbl>
## 1 Vesper mouse    Calomys     <NA>  Rodentia              7.00    NA    
## 2 Desert hedgehog Paraechinus <NA>  Erinaceomorpha       10.3      2.70 
## 3 Deer mouse      Peromyscus  <NA>  Rodentia             11.5     NA    
## 4 Phalanger       Phalanger   <NA>  Diprotodontia        13.7      1.80 
## 5 Rock hyrax      Procavia    <NA>  Hyracoidea            5.40     0.500
## 6 Mole rat        Spalax      <NA>  Rodentia             10.6      2.40 
## 7 Musk shrew      Suncus      <NA>  Soricomorpha         12.8      2.00

Similarly, you can add is.numeric, is.integer, is.double, is.logical, is.factor. If you have data columns, you can load the lubridate package, and use is.POSIXt or is.Date.

Filter at

其中一個更強大的函數是filter_at():它不會過濾所有列,也不需要你指定列的類型,你可以通過`vars()選擇要發生更改的列。 論據。 這個參數允許在select語句中完成任何事情:所以你可以通過名稱來引用它們,也可以通過邏輯數字函數,正則表達式等來引用它們(請參閱我的第一篇博客文章中的選擇選項)。

第二個參數是選擇的條件。 與上面的示例類似,如果所有列都需要返回TRUE(AND等效),則可以使用all_vars();如果只需要一個變量返回TRUE(OR等效),則可以使用any_vars()

示例:按名稱引用列:

msleep %>% 
  select(name, sleep_total:sleep_rem, brainwt:bodywt) %>% 
  filter_at(vars(sleep_total, sleep_rem), all_vars(.>5))

## # A tibble: 2 x 5
##   name                 sleep_total sleep_rem brainwt bodywt
##   <chr>                      <dbl>     <dbl>   <dbl>  <dbl>
## 1 Thick-tailed opposum        19.4      6.60 NA       0.370
## 2 Giant armadillo             18.1      6.10  0.0810 60.0

Example: using another select option:

msleep %>% 
  select(name, sleep_total:sleep_rem, brainwt:bodywt) %>% 
  filter_at(vars(contains("sleep")), all_vars(.>5))

## # A tibble: 2 x 5
##   name                 sleep_total sleep_rem brainwt bodywt
##   <chr>                      <dbl>     <dbl>   <dbl>  <dbl>
## 1 Thick-tailed opposum        19.4      6.60 NA       0.370
## 2 Giant armadillo             18.1      6.10  0.0810 60.0
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章