R语言ETL系列:过滤(filter)

浏览: 1517

作者:黄天元,复旦大学博士在读,目前研究涉及文本挖掘、社交网络分析和机器学习等。希望与大家分享学习经验,推广并加深R语言在业界的应用。

邮箱:huang.tian-yuan@qq.com

前言

本章节介绍如何根据条件对表格进行过滤,主要使用filter函数进行实现。
首先加载需要的包和数据,我们会用到R语言自带的mtcars数据集。首先我们把行的名称转化为一列数据,名为rownams。然后,把数据库转化为tibble格式,存在mtcars1变量中。

1library(tidyverse)
2
3mtcars %>%
4  rownames_to_column() %>%
5  as_tibble() -mtcars1
6
7mtcars1
8## # A tibble: 32 x 12
9##    rowname   mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear
10##    <chr>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
11##  1 Mazda ~  21       6  160    110  3.9   2.62  16.5     0     1     4
12##  2 Mazda ~  21       6  160    110  3.9   2.88  17.0     0     1     4
13##  3 Datsun~  22.8     4  108     93  3.85  2.32  18.6     1     1     4
14##  4 Hornet~  21.4     6  258    110  3.08  3.22  19.4     1     0     3
15##  5 Hornet~  18.7     8  360    175  3.15  3.44  17.0     0     0     3
16##  6 Valiant  18.1     6  225    105  2.76  3.46  20.2     1     0     3
17##  7 Duster~  14.3     8  360    245  3.21  3.57  15.8     0     0     3
18##  8 Merc 2~  24.4     4  147.    62  3.69  3.19  20       1     0     4
19##  9 Merc 2~  22.8     4  141.    95  3.92  3.15  22.9     1     0     4
20## 10 Merc 2~  19.2     6  168.   123  3.92  3.44  18.3     1     0     4
21## # ... with 22 more rowsand 1 more variablecarb <dbl>

条件过滤:filter

实际工作中,经常会需要用到把一定条件的记录调出来的情况。比如,如果我是超市的数据分析师,我需要查看单次消费超过500元的购物清单,就需要用到条件过滤。在我们的例子中,比如我们需要提取cyl为4的记录(cyl代表汽车气缸的数量),就可以这么操作:

1mtcars1 %>%
2  filter(cyl == 4)
3## # A tibble: 11 x 12
4##    rowname   mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear
5##    <chr>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
6##  1 Datsun~  22.8     4 108      93  3.85  2.32  18.6     1     1     4
7##  2 Merc 2~  24.4     4 147.     62  3.69  3.19  20       1     0     4
8##  3 Merc 2~  22.8     4 141.     95  3.92  3.15  22.9     1     0     4
9##  4 Fiat 1~  32.4     4  78.7    66  4.08  2.2   19.5     1     1     4
10##  5 Honda ~  30.4     4  75.7    52  4.93  1.62  18.5     1     1     4
11##  6 Toyota~  33.9     4  71.1    65  4.22  1.84  19.9     1     1     4
12##  7 Toyota~  21.5     4 120.     97  3.7   2.46  20.0     1     0     3
13##  8 Fiat X~  27.3     4  79      66  4.08  1.94  18.9     1     1     4
14##  9 Porsch~  26       4 120.     91  4.43  2.14  16.7     0     1     5
15## 10 Lotus ~  30.4     4  95.1   113  3.77  1.51  16.9     1     1     5
16## 11 Volvo ~  21.4     4 121     109  4.11  2.78  18.6     1     1     4
17## # ... with 1 more variable: carb <dbl>

结果中我们可以看到,气缸数量为4的记录都被我们调出来了。相关SQL代码如下

1<SQL> SELECT *
2FROM `mtcars1`
3WHERE (`cyl` = 4.0)

如何定义条件

什么是条件?很简单,是或不是。比如上面的例子,如果cyl等于4,就符合条件,否则不符合条件。因此只要我们的语句能够返回一个逻辑值(也就是计算机能够读懂的TURE或者FALSE),那么就能够构成一个条件。基本的条件操作符如下所示:

下面我们再举一个实际例子,比如我们需要除了4个气缸以外的数据,可以这么写:

1mtcars1 %>%
2  filter(cyl != 4)
3## # A tibble: 21 x 12
4##    rowname   mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear
5##    <chr>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
6##  1 Mazda ~  21       6  160    110  3.9   2.62  16.5     0     1     4
7##  2 Mazda ~  21       6  160    110  3.9   2.88  17.0     0     1     4
8##  3 Hornet~  21.4     6  258    110  3.08  3.22  19.4     1     0     3
9##  4 Hornet~  18.7     8  360    175  3.15  3.44  17.0     0     0     3
10##  5 Valiant  18.1     6  225    105  2.76  3.46  20.2     1     0     3
11##  6 Duster~  14.3     8  360    245  3.21  3.57  15.8     0     0     3
12##  7 Merc 2~  19.2     6  168.   123  3.92  3.44  18.3     1     0     4
13##  8 Merc 2~  17.8     6  168.   123  3.92  3.44  18.9     1     0     4
14##  9 Merc 4~  16.4     8  276.   180  3.07  4.07  17.4     0     0     3
15## 10 Merc 4~  17.3     8  276.   180  3.07  3.73  17.6     0     0     3
16## # ... with 11 more rows, and 1 more variable: carb <dbl>

SQL代码如下:

1<SQL> SELECT *
2FROM `mtcars1`
3WHERE (`cyl` != 4.0)

过滤缺失值

现实生产或商务活动中,总会有一些数据采集不到,这时候就会出现缺失值。作分析的时候,如果有缺失值,就无法进行正确计算,比如计算均值的时候,就不容许数据中包含缺失值。如何去除掉缺失值呢?这里我们可以使用drop_na函数。

下面我们先构造一个3*2的数据框,并在里面设置缺失值。例子如下:

1df <- tibble(x = c(1, 2, NA), y = c("a", NA, "b"))
2df #原始数据框
3## # A tibble: 3 x 2
4##       x y    
5##   <dbl> <chr>
6## 1     1 a    
7## 2     2 <NA> 
8## 3    NA b
9df %>% drop_na()   #去掉含有缺失值的行
10## # A tibble: 1 x 2
11##       x y    
12##   <dbl> <chr>
13## 1     1 a
14df %>% drop_na(x)  #去掉x列含有缺失值的行
15## # A tibble: 2 x 2
16##       x y    
17##   <dbl> <chr>
18## 1     1 a    
19## 2     2 <NA>

我们可以看到,使用drop_na函数,我们可以轻松地去掉包含缺失值的行,而且还可以指定去除某列中含有缺失值的行。那么,我们怎么找到这些具有缺失值的行呢?非常简单,利用is.na函数即可,例子如下:

1df %>%
2  filter(is.na(x))
3## # A tibble: 1 x 2
4##       x y    
5##   <dbl> <chr>
6## 1    NA b

SQL代码如下:

1<SQL> SELECT *
2FROM `df`
3WHERE (((`x`) IS NULL))

组合过滤

如果只有一个条件,也许非常简单。但是条件很多的时候,我们就需要使用逻辑操作符来把条件组合起来,一起进行过滤。经典的逻辑操作符包括&(与)、|(或)、!(非),有的编程语言会用英语AND/OR/NOT来表示这些逻辑关系,但是在逻辑层面上表达是一致的。下面通过一个例子来说明这些逻辑关系:

  • &:如果顾客最近一周买了东西且(&)买的东西超过100元,那么我们把这些顾客的交易记录调出来;

  • |:如果顾客最近一周买了东西或者(|)购买东西的频率维持在一周一次,那么我们把这些顾客的交易记录调出来;

  • !:我们只考虑女性客户,因此男性客户都剔除(!)掉。

&

操作符

我们想要筛选气缸(cyl)为4,而且马力(hp)大于100的汽车。

1mtcars1 %>%
2  filter(cyl == 4 & hp > 100)
3## # A tibble: 2 x 12
4##   rowna~   mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
5##   <chr>  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
6## 1 Lotus~  30.4     4  95.1   113  3.77  1.51  16.9     1     1     5     2
7## 2 Volvo~  21.4     4 121     109  4.11  2.78  18.6     1     1     4     2
8#等价于
9mtcars1 %>%
10  filter(cyl == 4,hp > 100)
11## # A tibble: 2 x 12
12##   rowna~   mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
13##   <chr>  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
14## 1 Lotus~  30.4     4  95.1   113  3.77  1.51  16.9     1     1     5     2
15## 2 Volvo~  21.4     4 121     109  4.11  2.78  18.6     1     1     4     2

SQL代码如下:

1<SQL> SELECT *
2FROM `mtcars1`
3WHERE ((`cyl` = 4.0AND (`hp` > 100.0))

|

操作符

我们想要筛选气缸(cyl)为4,或者马力(hp)大于100的汽车。

1mtcars1 %>%
2  filter(cyl == 4 | hp > 100)
3## # A tibble: 32 x 12
4##    rowname   mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear
5##    <chr>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
6##  1 Mazda ~  21       6  160    110  3.9   2.62  16.5     0     1     4
7##  2 Mazda ~  21       6  160    110  3.9   2.88  17.0     0     1     4
8##  3 Datsun~  22.8     4  108     93  3.85  2.32  18.6     1     1     4
9##  4 Hornet~  21.4     6  258    110  3.08  3.22  19.4     1     0     3
10##  5 Hornet~  18.7     8  360    175  3.15  3.44  17.0     0     0     3
11##  6 Valiant  18.1     6  225    105  2.76  3.46  20.2     1     0     3
12##  7 Duster~  14.3     8  360    245  3.21  3.57  15.8     0     0     3
13##  8 Merc 2~  24.4     4  147.    62  3.69  3.19  20       1     0     4
14##  9 Merc 2~  22.8     4  141.    95  3.92  3.15  22.9     1     0     4
15## 10 Merc 2~  19.2     6  168.   123  3.92  3.44  18.3     1     0     4
16## # ... with 22 more rows, and 1 more variable: carb <dbl>

SQL代码如下:

1<SQL> SELECT *
2FROM `mtcars1`
3WHERE (`cyl` = 4.0 OR `hp` > 100.0)

!

操作符

我们想要筛选除了4个气缸以外的汽车记录。

1mtcars1 %>%
2  filter(!cyl == 4)
3## # A tibble: 21 x 12
4##    rowname   mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear
5##    <chr>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
6##  1 Mazda ~  21       6  160    110  3.9   2.62  16.5     0     1     4
7##  2 Mazda ~  21       6  160    110  3.9   2.88  17.0     0     1     4
8##  3 Hornet~  21.4     6  258    110  3.08  3.22  19.4     1     0     3
9##  4 Hornet~  18.7     8  360    175  3.15  3.44  17.0     0     0     3
10##  5 Valiant  18.1     6  225    105  2.76  3.46  20.2     1     0     3
11##  6 Duster~  14.3     8  360    245  3.21  3.57  15.8     0     0     3
12##  7 Merc 2~  19.2     6  168.   123  3.92  3.44  18.3     1     0     4
13##  8 Merc 2~  17.8     6  168.   123  3.92  3.44  18.9     1     0     4
14##  9 Merc 4~  16.4     8  276.   180  3.07  4.07  17.4     0     0     3
15## 10 Merc 4~  17.3     8  276.   180  3.07  3.73  17.6     0     0     3
16## # ... with 11 more rows, and 1 more variable: carb <dbl>
17#等价于
18mtcars1 %>%
19  filter(cyl != 4)
20## # A tibble: 21 x 12
21##    rowname   mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear
22##    <chr>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
23##  1 Mazda ~  21       6  160    110  3.9   2.62  16.5     0     1     4
24##  2 Mazda ~  21       6  160    110  3.9   2.88  17.0     0     1     4
25##  3 Hornet~  21.4     6  258    110  3.08  3.22  19.4     1     0     3
26##  4 Hornet~  18.7     8  360    175  3.15  3.44  17.0     0     0     3
27##  5 Valiant  18.1     6  225    105  2.76  3.46  20.2     1     0     3
28##  6 Duster~  14.3     8  360    245  3.21  3.57  15.8     0     0     3
29##  7 Merc 2~  19.2     6  168.   123  3.92  3.44  18.3     1     0     4
30##  8 Merc 2~  17.8     6  168.   123  3.92  3.44  18.9     1     0     4
31##  9 Merc 4~  16.4     8  276.   180  3.07  4.07  17.4     0     0     3
32## 10 Merc 4~  17.3     8  276.   180  3.07  3.73  17.6     0     0     3
33## # ... with 11 more rows, and 1 more variable: carb <dbl>

SQL代码如下:

1<SQL> SELECT *
2FROM `mtcars1`
3WHERE (NOT(`cyl` = 4.0))

文本过滤

数据表中的数据不都是数值型的,有的是字符串格式存在的文本。在我们的例子中,比如我们想了解Merc这个型号的车,那么我们就要从rowname列中个提取包含“Merc”的行。

R语言tidyverse包中,包含了stringr包,可以对字符串进行识别、替换、提取等高级操作。如果我们要根据字符串进行过滤,就需要用到str_detect函数,例子如下:

1#提取rowname中包含“Merc”的记录
2
3mtcars1 %>%
4  filter(str_detect(rowname,pattern = "Merc"))
5## # A tibble: 7 x 12
6##   rowna~   mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
7##   <chr>  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
8## 1 Merc ~  24.4     4  147.    62  3.69  3.19  20       1     0     4     2
9## 2 Merc ~  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2
10## 3 Merc ~  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4
11## 4 Merc ~  17.8     6  168.   123  3.92  3.44  18.9     1     0     4     4
12## 5 Merc ~  16.4     8  276.   180  3.07  4.07  17.4     0     0     3     3
13## 6 Merc ~  17.3     8  276.   180  3.07  3.73  17.6     0     0     3     3
14## 7 Merc ~  15.2     8  276.   180  3.07  3.78  18       0     0     3     3

SQL代码为:

1<SQL> SELECT *
2FROM `mtcars1`
3WHERE (INSTR('^Merc', `rowname`) > 0)

我们看到pattern参数中,我们赋予了“Merc”模式。事实上,pattern可以接受正则表达式的内容,比如我们要搜索以M开头的车型,那么就可以把pattern改为“^M”:

1mtcars1 %>%
2  filter(str_detect(rowname,pattern = "^M"))
3## # A tibble: 10 x 12
4##    rowname   mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear
5##    <chr>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
6##  1 Mazda ~  21       6  160    110  3.9   2.62  16.5     0     1     4
7##  2 Mazda ~  21       6  160    110  3.9   2.88  17.0     0     1     4
8##  3 Merc 2~  24.4     4  147.    62  3.69  3.19  20       1     0     4
9##  4 Merc 2~  22.8     4  141.    95  3.92  3.15  22.9     1     0     4
10##  5 Merc 2~  19.2     6  168.   123  3.92  3.44  18.3     1     0     4
11##  6 Merc 2~  17.8     6  168.   123  3.92  3.44  18.9     1     0     4
12##  7 Merc 4~  16.4     8  276.   180  3.07  4.07  17.4     0     0     3
13##  8 Merc 4~  17.3     8  276.   180  3.07  3.73  17.6     0     0     3
14##  9 Merc 4~  15.2     8  276.   180  3.07  3.78  18       0     0     3
15## 10 Masera~  15       8  301    335  3.54  3.57  14.6     0     1     5
16## # ... with 1 more variable: carb <dbl>

SQL代码为:

1<SQL> SELECT *
2FROM `mtcars1`
3WHERE (INSTR('^M', `rowname`) > 0)

正则表达式是一个很有用的工具,如果能够写出高效的正则表达式,就能够对字符串进行更加高级的筛选。不过正则表达式超出了本系列的范围,因此不进行更多的介绍。

本章介绍了如何用filter函数完成过滤,我们了解了如何通过构造条件来对数据表的记录进行筛选。此外,我们能够去掉表格中含有缺失值的数据,还能把这些缺失的记录单独提取出来。最后,我们学会了如何通过构造组合过滤来进行复杂的表格数据筛选,并知道如何利用str_detect函数对文本格式的数据进行筛选。

往期精彩:


公众号后台回复关键字即可学习

回复 爬虫            爬虫三大案例实战
回复 Python       1小时破冰入门
回复 数据挖掘     R语言入门及数据挖掘
回复 人工智能     三个月入门人工智能
回复 数据分析师  数据分析师成长之路 
回复 机器学习     机器学习的商业应用
回复 数据科学     数据科学实战
回复 常用算法     常用数据挖掘算法

推荐 0
本文由 R语言中文社区 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册