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ù)