欢迎关注天善智能,我们是专注于商业智能BI,人工智能AI,大数据分析与挖掘领域的垂直社区,学习,问答、求职一站式搞定!
对商业智能BI、大数据分析挖掘、机器学习,python,R等数据领域感兴趣的同学加微信:tstoutiao,邀请你进入数据爱好者交流群,数据爱好者们都在这儿。
作者:黄天元,复旦大学博士在读,目前研究涉及文本挖掘、社交网络分析和机器学习等。希望与大家分享学习经验,推广并加深R语言在业界的应用。
邮箱:[email protected]
有没有一些时候你想要给表格加一个新的列?本章将会介绍如何在表格中创建新的字段。但是首先我们要知道为什么要什么做,下面是可能的一些情况:
有时候需要构造一列全部是0或1的数列,或者是给每一个记录赋予一个不同的ID;
购物数据中,含有单价和数量,需要计算交易额,然后加入到表格中;
我们数据中有年月日的数据,我们需要把它们拼接成一个字符格式,比如,2018年10月10日,我们需要表示为20181010或者2018/10/10;
在tidyverse中,我们可以用mutate函数给表格增加新的一列。下面将会分节介绍,首先载入我们需要的数据和包:
1library(tidyverse)
2library(nycflights1
添加常数列
这里举一个简单的例子,用iris数据集,增加一个完全为0的新列,我们会限制输出列为前六行,以免输出内容过多。
1iris %>%
2 mutate(zeros = 0) %>%
3 head
4## Sepal.Length Sepal.Width Petal.Length Petal.Width Species zeros
5## 1 5.1 3.5 1.4 0.2 setosa 0
6## 2 4.9 3.0 1.4 0.2 setosa 0
7## 3 4.7 3.2 1.3 0.2 setosa 0
8## 4 4.6 3.1 1.5 0.2 setosa 0
9## 5 5.0 3.6 1.4 0.2 setosa 0
10## 6 5.4 3.9 1.7 0.4 setosa 0
可以看到我们已经新增了一列,名字叫做zeros,里面的值全部是0。 SQL代码如下:
1<SQL> SELECT `Sepal.Length`, `Sepal.Width`, `Petal.Length`, `Petal.Width`, `Species`, 0.0 AS `zeros`
2FROM `iris`
算数运算
本例会用到flights数据,这个表中包含了航班的起飞时间(dep_time)和到达时间(arr_time),如果需要知道中间经理了多长时间,我们需要将两者相减。我们会先把两列取出来,然后再构造新的列:
1flights %>%
2 select(dep_time,arr_time) %>%
3 mutate(time = arr_time - dep_time)
4## # A tibble: 336,776 x 3
5## dep_time arr_time time
6## <int> <int> <int>
7## 1 517 830 313
8## 2 533 850 317
9## 3 542 923 381
10## 4 544 1004 460
11## 5 554 812 258
12## 6 554 740 186
13## 7 555 913 358
14## 8 557 709 152
15## 9 557 838 281
16## 10 558 753 195
17## # ... with 336,766 more rows
这样一来我们就把飞行时间储存在time列中。事实上我们还可以这么表达:
1flights %>%
2 transmute(dep_time,arr_time,time = arr_time - dep_time)
3## # A tibble: 336,776 x 3
4## dep_time arr_time time
5## <int> <int> <int>
6## 1 517 830 313
7## 2 533 850 317
8## 3 542 923 381
9## 4 544 1004 460
10## 5 554 812 258
11## 6 554 740 186
12## 7 555 913 358
13## 8 557 709 152
14## 9 557 838 281
15## 10 558 753 195
16## # ... with 336,766 more rows
得到结果与上面一致。transmute函数的特点就是,不会保存数据表中原有的列,自动完成了select的功能。
SQL代码如下:
1<SQL> SELECT `dep_time`, `arr_time`, `arr_time` - `dep_time` AS `time`
2FROM (SELECT `dep_time`, `arr_time`
3FROM `flights`)
文本的拼接与拆分
这个例子中,我们来看flights数据,它包含了年(year)、月(month)、日(day)、起始点(origin)、终点(dest)的数据列,首先我们把这些列取出来存放到新的变量中,并进行观察:
1flights %>%
2 select(year,month,day,origin,dest) -> fl_ymd
3
4fl_ymd
5## # A tibble: 336,776 x 5
6## year month day origin dest
7## <int> <int> <int> <chr> <chr>
8## 1 2013 1 1 EWR IAH
9## 2 2013 1 1 LGA IAH
10## 3 2013 1 1 JFK MIA
11## 4 2013 1 1 JFK BQN
12## 5 2013 1 1 LGA ATL
13## 6 2013 1 1 EWR ORD
14## 7 2013 1 1 EWR FLL
15## 8 2013 1 1 LGA IAD
16## 9 2013 1 1 JFK MCO
17## 10 2013 1 1 LGA ORD
18## # ... with 336,766 more rows
拼
接
现在,我们想要把第一行的起始点和终点拼接为“EWR_IAH”的格式,放在名为origin_dest的列中,下面我们进行操作:
1fl_ymd %>%
2 mutate(origin_dest = str_c(origin,dest,sep = "_")) -> fl_ymd.1
3
4fl_ymd.1
5## # A tibble: 336,776 x 6
6## year month day origin dest origin_dest
7## <int> <int> <int> <chr> <chr> <chr>
8## 1 2013 1 1 EWR IAH EWR_IAH
9## 2 2013 1 1 LGA IAH LGA_IAH
10## 3 2013 1 1 JFK MIA JFK_MIA
11## 4 2013 1 1 JFK BQN JFK_BQN
12## 5 2013 1 1 LGA ATL LGA_ATL
13## 6 2013 1 1 EWR ORD EWR_ORD
14## 7 2013 1 1 EWR FLL EWR_FLL
15## 8 2013 1 1 LGA IAD LGA_IAD
16## 9 2013 1 1 JFK MCO JFK_MCO
17## 10 2013 1 1 LGA ORD LGA_ORD
18## # ... with 336,766 more rows
我们可以看到,使用mutate函数可以增加一列,而这一列通过str_c函数,把两列拼接起来,中间的分隔符号设定为下划线(“_“)。此外,我们可以用unite函数完成这个任务:
1#等价于
2fl_ymd %>%
3 unite(col = origin_dest,origin,dest) -> fl_ymd.2
4
5fl_ymd.2
6## # A tibble: 336,776 x 4
7## year month day origin_dest
8## <int> <int> <int> <chr>
9## 1 2013 1 1 EWR_IAH
10## 2 2013 1 1 LGA_IAH
11## 3 2013 1 1 JFK_MIA
12## 4 2013 1 1 JFK_BQN
13## 5 2013 1 1 LGA_ATL
14## 6 2013 1 1 EWR_ORD
15## 7 2013 1 1 EWR_FLL
16## 8 2013 1 1 LGA_IAD
17## 9 2013 1 1 JFK_MCO
18## 10 2013 1 1 LGA_ORD
19## # ... with 336,766 more rows
unite中的col参数是新的列名称,后面可以放任意多的列,最后会把放进去的列都拼接起来。
unite函数是专门用来对不同列之间字符串进行拼接的函数,默认的间隔符号就是“_”,但是可以通过sep参数改变分隔符。此外,我们可以注意到,如果利用unite函数,原始的两列origin和dest会消失,而mutate则是单纯增加一列。
拆
分
那么,如果我们想要把已经拼接好的数据拆分出来,应该怎么做呢?
我们现在就来对flm_ymd.2的origin_dest列进行拆分操作,这里我们会用到separate函数:
1fl_ymd.2 %>%
2 separate(col = origin_dest, into = c("origin","dest"))
3## # A tibble: 336,776 x 5
4## year month day origin dest
5## <int> <int> <int> <chr> <chr>
6## 1 2013 1 1 EWR IAH
7## 2 2013 1 1 LGA IAH
8## 3 2013 1 1 JFK MIA
9## 4 2013 1 1 JFK BQN
10## 5 2013 1 1 LGA ATL
11## 6 2013 1 1 EWR ORD
12## 7 2013 1 1 EWR FLL
13## 8 2013 1 1 LGA IAD
14## 9 2013 1 1 JFK MCO
15## 10 2013 1 1 LGA ORD
16## # ... with 336,766 more rows
我们可以看到,separate其实是unite的逆运算,col中赋值的是需要拆分的列名称,into则是拆分之后不同部分的名称。 separate也有sep参数,可以调整参数来根据特殊符号进行拆分,默认的拆分参数是所有非字母符号。如果大家要用中文的话,应该注意,一定要使用sep参数,也就是应该写成“fl_ymd.2 %>% separate(col =origin_dest, into = c(”origin“,”dest“),sep =”_“)”。
总
结
本章中,我们讲了如何用mutate创建字段。我们可以灵活地使用mutate函数,构造一个常数列,或者基于原始的数据列进行数学运算,从而构成新的列。这些知识对于机器学习中的特征工程尤为重要,是必须掌握的基础。最后,我们还介绍了如何对字符型的变量进行拼接和拆分,如果需要进行文本挖掘的话,这些技能是必不可少的。
往期精彩:
公众号后台回复关键字即可学习
回复 爬虫 爬虫三大案例实战
回复 Python 1小时破冰入门
回复 数据挖掘 R语言入门及数据挖掘
回复 人工智能 三个月入门人工智能
回复 数据分析师 数据分析师成长之路
回复 机器学习 机器学习的商业应用
回复 数据科学 数据科学实战
回复 常用算法 常用数据挖掘算法
请发表评论