数据处理第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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏互联网开发者交流社区

使用Java实现面向对象编程

1222
来自专栏mini188

java中的锁

java中有哪些锁 这个问题在我看了一遍<java并发编程>后尽然无法回答,说明自己对于锁的概念了解的不够。于是再次翻看了一下书里的内容,突然有点打开脑门的感觉...

3979
来自专栏QQ音乐技术团队的专栏

iOS 中的 Promise 设计模式

无论是代理模式,还是闭包,在处理单一任务的时候,都出色的完成了任务。可是当两种模式要相互配合,一起完成一系列任务,并且每个任务之间还要共享信息,相互衔接,雇主就...

2020
来自专栏大内老A

[ASP.NET MVC]通过对HtmlHelper扩展简化“列表控件”的绑定

在众多表单元素中,有一类<select>元素用于绑定一组预定义列表。传统的ASP.NET Web Form中,它对应着一组重要的控件类型,即ListContro...

1935
来自专栏程序员维他命

iOS 代码规范

花了一个月的时间结合几篇博客和书籍写了这套 iOS 代码规范(具体参考底部的参考文献部分)。这套代码规范除了有仅适用于 iOS 开发的部分,还有其他的比较通用性...

1912
来自专栏FreeBuf

浅析ReDoS的原理与实践

*本文原创作者:MyKings,本文属FreeBuf原创奖励计划,未经许可禁止转载 ReDoS(Regular expression Denial of Ser...

6575
来自专栏祝威廉

ElasticSearch Aggregations GroupBy 实现源码分析

也就是按newtype 字段进行group by,然后对num求平均值。在我们实际的业务系统中,这种统计需求也是最多的。

3593
来自专栏社区的朋友们

iOS 中的 Promise 设计模式

无论是代理模式,还是闭包,在处理单一任务的时候,都出色的完成了任务。可是当两种模式要相互配合,一起完成一系列任务,并且每个任务之间还要共享信息,相互衔接,雇主就...

2.2K1
来自专栏文武兼修ing——机器学习与IC设计

开放地址法散列开放地址法代码实现

开放地址法 开放地址法是另一种(相对于分离链接法)解决散列冲突的方法。适用于装填因子(散列表中元素个数和散列表长度比)较小(小于0.5)的散列表。 开放地址法中...

44712
来自专栏nimomeng的自我进阶

Collection官方文档

a) Keys必须实现NSCopying协议。添加成员的方法并不将每一个key直接进行添加,而是将每一个key进行copy并将copy后对象添加...

1514

扫码关注云+社区

领取腾讯云代金券