R語(yǔ)言常用語(yǔ)法
R語(yǔ)言中的管道%>%
%>%來自dplyr包的管道函數(shù),我們可以將其理解為車間里的流水線,經(jīng)過前一步加工的產(chǎn)品才能進(jìn)入后一步進(jìn)一步加工,其作用是將前一步的結(jié)果直接傳參給下一步的函數(shù),從而省略了中間的賦值步驟,可以大量減少內(nèi)存中的對(duì)象,節(jié)省內(nèi)存。
符號(hào)%>%,這是管道操作,其意思是將%>%左邊的對(duì)象傳遞給右邊的函數(shù),作為第一個(gè)選項(xiàng)的設(shè)置(或剩下唯一一個(gè)選項(xiàng)的設(shè)置。
簡(jiǎn)單例子
比如我們要算f(x)=sin((x+1)^2)在x=4的值,可以分為以下三步:
- 計(jì)算a = x+1的值;
- 計(jì)算b = a^2的值;
- 計(jì)算c = sin(b)的值
這樣一來,c就是我們需要的最終結(jié)果了。用R語(yǔ)言管道傳參,只需要這樣寫:
f1 <- function(x){return(x+1)} f2 <- function(x){return(x^2)} f3 <- function(x){return(sin(x))}
管道(%>%)調(diào)用函數(shù)
library(dplyr) #用管道傳參需要這個(gè)包
a <- 1 b <- a %>% f1 %>% f2 %>% f3 print(b) [1] -0.7568025
管道傳參具體用法
a%>%f(b)等同于f(a,b);
b%>%f(a,.,c)等同于f(a,b,c);
例如:
>library(dplyr) > f1 <- function(x,y){return(x+y)} > f2 <- function(x,y,z){return(x*y+z)} > a1 <- 2 > a2 <- 3 > a3 <- 4 > d1 <- a1 %>% f1(a2) > d1 [1] 5 > d2 <- a2 %>% f2(a1,.,a3) > d2 [1] 10 > d3 <- a3 %>% f2(a1,a2,.) > d3 [1] 10
創(chuàng)建一份數(shù)據(jù):
> library(tidyr) >date <- as.Date('2017-6-22')+0:14 > hour <- sample(1:24, 15) > min <- sample(1:60, 15) > second <- sample(1:60, 15) > dat <- data.frame(date,hour,min,second) > dat date hour min second 1 2017-06-22 22 54 15 2 2017-06-23 7 51 4 3 2017-06-24 11 23 38 4 2017-06-25 23 45 50 5 2017-06-26 14 60 44 6 2017-06-27 5 24 56 7 2017-06-28 9 39 25 8 2017-06-29 20 22 22 9 2017-06-30 2 17 43 10 2017-07-01 17 56 31 11 2017-07-02 19 11 33 12 2017-07-03 24 35 18 13 2017-07-04 15 6 13 14 2017-07-05 4 12 47 15 2017-07-06 12 7 30
我們想把它變成標(biāo)準(zhǔn)時(shí)間格式,怎么辦呢?“tidyr”包的函數(shù)unite()可以以指定字符連接指定列,形成新列,具體用法見下例:
> a1 <- rep(1,5) > a2 <- rep(2,5) > a3 <- rep(3,5) > A <- data.frame(a1,a2,a3) > A a1 a2 a3 1 1 2 3 2 1 2 3 3 1 2 3 4 1 2 3 5 1 2 3 > A1 <- unite(A,a12,a1,a2,sep = '~')
或者> A1 <- A %>% unite(a12,a1,a2,sep = '~')
對(duì)數(shù)據(jù)A的列a1,a2合并為新列a12,用“~”連接。
> A1 a12 a3 1 1~2 3 2 1~2 3 3 1~2 3 4 1~2 3 5 1~2 3
再來一步:
> A2 <- unite(A1,a123,a12,a3,sep = '/') > A2 <- A1 %>% unite(a123,a12,a3,sep = '/')
對(duì)A1里面的a12與a3用“/”連接,形成新列“a123”。
> A2 a123 1 1~2/3 2 1~2/3 3 1~2/3 4 1~2/3 5 1~2/3
也可以用管道傳參一步搞定:
> A %>%unite(a12,a1,a2,sep = '~') %>% unite(a123,a12,a3,sep = '/') a123 1 1~2/3 2 1~2/3 3 1~2/3 4 1~2/3 5 1~2/3
回到我們的問題
看懂上例,就可以用管道傳參一步搞定時(shí)間轉(zhuǎn)換問題。
> dat1 <- dat %>%unite(datehour,date,hour,sep = ' ')%>%unite(datetime,datehour,min,second,sep = ':') > dat1 datetime 1 2017-06-22 22:54:15 2 2017-06-23 7:51:4 3 2017-06-24 11:23:38 4 2017-06-25 23:45:50 5 2017-06-26 14:60:44 6 2017-06-27 5:24:56 7 2017-06-28 9:39:25 8 2017-06-29 20:22:22 9 2017-06-30 2:17:43 10 2017-07-01 17:56:31 11 2017-07-02 19:11:33 12 2017-07-03 24:35:18 13 2017-07-04 15:6:13 14 2017-07-05 4:12:47 15 2017-07-06 12:7:30
R語(yǔ)言調(diào)試
請(qǐng)小心上述代碼中的漏洞(bug),我只證明了代碼是正確的,而沒有嘗試過。
——Donald Knuth,計(jì)算機(jī)科學(xué)先驅(qū)
程序員經(jīng)常會(huì)發(fā)現(xiàn)他們?cè)谡{(diào)試程序上花費(fèi)的時(shí)間比編寫程序本身花的時(shí)間還要長(zhǎng),所以好的調(diào)試技巧是無(wú)價(jià)的。
這里介紹R語(yǔ)言基本調(diào)試方法。R語(yǔ)言調(diào)試工具由瀏覽器(browser)構(gòu)成,它可以使我們的程序逐行運(yùn)行,可以調(diào)用debug()或者browser()函數(shù)打開瀏覽器。
瀏覽器調(diào)試命令
進(jìn)入調(diào)試瀏覽器時(shí),命令提示符從“>”變?yōu)椤癇rowse[d]>”(“d”表示函數(shù)調(diào)用鏈深度)
1. n(next):執(zhí)行下一行,然后暫停,直接鍵入“Enter”一樣;
2. c(continue):如果在循環(huán)中,會(huì)執(zhí)行本次循環(huán)剩下所有語(yǔ)句,然后進(jìn)入下一次循環(huán),到該位置繼續(xù)暫停;
鍵入變量名:查看變量值,若與瀏覽器變量同名,需用print()打印出來看,下面有例子,旁邊變量區(qū)也可以看;
3. where:顯示到達(dá)當(dāng)前位置過程中函數(shù)的調(diào)用序列;
4. Q:該命令會(huì)退出瀏覽器,返回正常交互模式。
debug()
debug(f)函數(shù)可以在函數(shù)f()入口處進(jìn)入瀏覽器而處于調(diào)試狀態(tài)。
比如這個(gè)例子:
cou <- function(count) { s <- 0 i <- 1 while(i<count+1) { s <- s+i i <- i+1 } return(s) } debug(cou) cou(10)
只在入口處調(diào)試一次:
Browse[2]> c exiting from: cou(10) [1] 55
結(jié)束。
browser()
與debug(f)函數(shù)在函數(shù)f()入口處進(jìn)入瀏覽器而處于調(diào)試狀態(tài)不同,browser()可以插在函數(shù)中任一行,程序只要運(yùn)行到該行,就進(jìn)入調(diào)試狀態(tài)即瀏覽器會(huì)被打開,直到程序結(jié)束。
假如我們想觀察這個(gè)累加運(yùn)算過程變量i、s的變化,可以把browser()加到循環(huán)中,每循環(huán)一次,暫停一次,便于觀察。
cou1 <- function(count) { s <- 0 i <- 1 while(i<count+1) { s <- s+i browser() #-----調(diào)試處-----# i <- i+1 } return(s) } cou1(10)
第一次調(diào)試
我們查看i、s的值
Called from: cou1(10) Browse[1]> i [1] 1 Browse[1]> print(s) [1] 1
輸入“c”(continue縮寫)執(zhí)行下一次循環(huán)。
Browse[1]> c Called from: cou1(10) Browse[1]> i [1] 2 Browse[1]> print(s) [1] 3 ...
第十次調(diào)試
Browse[1]> c Called from: cou1(10) Browse[1]> i [1] 10 Browse[1]> print(s) [1] 55 結(jié)束 Browse[1]> c [1] 55
作者:柯廣的網(wǎng)絡(luò)日志
微信公眾號(hào):Java大數(shù)據(jù)與數(shù)據(jù)倉(cāng)庫(kù)