R語言ETL系列:創建字段(mutate)

R語言ETL系列:創建字段(mutate)

歡迎關注天善智能,我們是專注於商業智能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 
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##
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##
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 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##
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##

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##
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##

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函數,構造一個常數列,或者基於原始的數據列進行數學運算,從而構成新的列。這些知識對於機器學習中的特徵工程尤為重要,是必須掌握的基礎。最後,我們還介紹瞭如何對字符型的變量進行拼接和拆分,如果需要進行文本挖掘的話,這些技能是必不可少的。

R語言ETL系列:創建字段(mutate)

往期精彩:

  • “IT男等級”對照表|找找你在哪?
  • 不用代碼,從搜索數據中解讀星巴克“貓爪杯”如何撓你的心
  • 功不唐捐,每日一道LeetCode,玉汝於成,終獲offer滿滿!
  • R語言中文社區2018年終文章整理(作者篇)
  • R語言中文社區2018年終文章整理(類型篇)
R語言ETL系列:創建字段(mutate)

回覆 爬蟲 爬蟲三大案例實戰

回覆 Python 1小時破冰入門

回覆 數據挖掘 R語言入門及數據挖掘

回覆 人工智能 三個月入門人工智能

回覆 數據分析師 數據分析師成長之路

回覆 機器學習 機器學習的商業應用

回覆 數據科學 數據科學實戰

回覆 常用算法 常用數據挖掘算法


分享到:


相關文章: