日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
5分鐘解讀Python中的鏈?zhǔn)秸{(diào)用

如果你是有打算從事有關(guān)數(shù)據(jù)分析或者數(shù)據(jù)挖掘的等數(shù)據(jù)科學(xué)領(lǐng)域的工作,或者和我一樣目前就是從事相關(guān)領(lǐng)域的工作,那么「鏈?zhǔn)秸{(diào)用」對我們而言是一門必修課。

我們提供的服務(wù)有:成都網(wǎng)站設(shè)計、成都網(wǎng)站建設(shè)、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、開魯ssl等。為上千余家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的開魯網(wǎng)站制作公司

為什么是鏈?zhǔn)秸{(diào)用?

鏈?zhǔn)秸{(diào)用,或者也可以稱為方法鏈(Method Chaining),從字面意思上來說就是將一些列的操作或函數(shù)方法像鏈子一樣穿起來的 Code 方式。

我最開始感知鏈?zhǔn)秸{(diào)用的「美」,還要從使用 R 語言的管道操作符開始。

 
 
 
 
  1. library(tidyverse)
  2. mtcars %>%  
  3.   group_by(cyl) %>%  
  4.   summarise(meanmeanOfdisp = mean(disp)) %>%  
  5.   ggplot(aes(x=as.factor(cyl), y=meanOfdisp, fill=as.factor(seq(1,3))))+ 
  6.   geom_bar(stat = 'identity') +  
  7.   guides(fill=F)

對于 R user 來說,對于這一段代碼很快就能明白整個流程步驟是怎樣的。這一切都是通過符號%>%(管道操作符)談起。

通過管道操作符,我們可以將左邊事物傳遞給下一個事物。這里我將mtcars數(shù)據(jù)集傳遞到group_by 函數(shù)中,然后將得到后的結(jié)果再傳遞到summarize函數(shù),最后傳遞到ggplot函數(shù)中進行可視化繪制。

如果我沒有學(xué)會鏈?zhǔn)秸{(diào)用,那么最開始學(xué)習(xí) R 語言的我一定是這樣寫:

 
 
 
 
  1. library(tidyverse) 
  2. cyl4 <- mtcars[which(mtcars$cyl==4), ] 
  3. cyl6 <- mtcars[which(mtcars$cyl==6), ] 
  4. cyl8 <- mtcars[which(mtcars$cyl==8), ] 
  5. data <- data.frame( 
  6.   ccyl = c(4, 6, 8), 
  7.   meanOfdisp = c(mean(cyl4$disp), mean(cyl6$disp), mean(cyl8$disp)) 
  8. graph <- ggplot(datadata=data, aes(x=factor(cyl), y=meanOfdisp,  
  9.                                fill = as.factor(seq(1,3))))  
  10. graph <- graph + geom_bar(stat = 'identity') + guides(fill=F) 
  11. graph

如果不使用管道操作符,那么我將會進行不必要的賦值,并且覆蓋原有的數(shù)據(jù)對象,但其實當(dāng)中產(chǎn)生的cyl#、data 其實最后都只是為graph 這一張圖片所服務(wù)的,因此導(dǎo)致的問題就是代碼會變得冗余。

鏈?zhǔn)秸{(diào)用在極大程度簡潔代碼的同時,也提高了代碼的可讀性,能夠很快速地了解到每一步都是在做什么。這種方式對于做數(shù)據(jù)分析或處理數(shù)據(jù)時是十分有用,減少創(chuàng)建不必要的變量時,能夠以快速、簡單的方式進行探索。

你能在很多地方見到鏈?zhǔn)秸{(diào)用或者管道操作的身影,這里我舉除了 R 語言以外的兩個典型例子。

一個是 Shell 語句:

 
 
 
 
  1. echo "`seq 1 100`" | grep -e "^[3-4].*" | tr "3" "*"

在 shell 語句中使用「|」管道操作符能夠快速地實現(xiàn)鏈?zhǔn)秸{(diào)用,這里我首先是打印1-100的所有整數(shù),然后將其傳入到grep方法中,提取由 3 或 4 開頭的所有部分,再將這部分傳入到tr 方法中,并對數(shù)字包含 3 的部分用星號替換。結(jié)果如下:

另外一個是 Scala 語言:

 
 
 
 
  1. object Test { 
  2.   def main(args: Array[String]): Unit = { 
  3.     val numOfseq = (1 to 100).toList 
  4.     val chain = numOfseq.filter(_%2==0) 
  5.       .map(_*2) 
  6.       .take(10) 
  7.   } 
  8. }

在這段示例中,首先numOfseq 這個變量包含了從 1-100 的所有整數(shù),然后從chain部分開始,我首先在numOfseq的基礎(chǔ)上調(diào)用了filter 方法,用以篩選這些數(shù)字中為偶數(shù)的部分,其次在調(diào)用map 方法,將這些被篩選出來的數(shù)乘以 2,最后使用take 方法從新構(gòu)成的數(shù)字中取出前 10 個數(shù),這些數(shù)共同賦值給了chain 變量。

通過以上的敘述,相信你能對鏈?zhǔn)秸{(diào)用有一個初步的印象,但是一旦你掌握了鏈?zhǔn)秸{(diào)用,那么除了會讓你的代碼風(fēng)格有所改變以外,你的編程思維也會有不一樣的提升。

Python 中的鏈?zhǔn)秸{(diào)用

在 Python 中實現(xiàn)一個簡單的鏈?zhǔn)秸{(diào)用就是通過構(gòu)建類方法并返回對象自身或返回歸屬類(@classmethod)

 
 
 
 
  1. class Chain: 
  2.     def __init__(self, name): 
  3.         self.name = name 
  4.     def introduce(self): 
  5.         print("hello, my name is %s" % self.name) 
  6.         return self 
  7.     def talk(self): 
  8.         print("Can we make a friend?") 
  9.         return self 
  10.     def greet(self): 
  11.         print("Hey! How are you?") 
  12.         return self
  13. if __name__ == '__main__': 
  14.     chain = Chain(name = "jobs") 
  15.     chain.introduce() 
  16.     print("-"*20) 
  17.     chain.introduce().talk() 
  18.     print("-"*20) 
  19.     chain.introduce().talk().greet()

在這里我們創(chuàng)建一個Chain 類,需要傳遞一個name 字符串參數(shù)進行實例對象的創(chuàng)建;當(dāng)中這個類里有三個方法,分別是introduce、talk以及greet。

由于每次返回的是self 自身,那么我們就可以源源不斷地調(diào)用對象歸屬類中的方法,結(jié)果如下:

 
 
 
 
  1. hello, my name is jobs 
  2. -------------------- 
  3. hello, my name is jobs 
  4. Can we make a friend? 
  5. -------------------- 
  6. hello, my name is jobs 
  7. Can we make a friend? 
  8. Hey! How are you?

在 Pandas 中使用鏈?zhǔn)秸{(diào)用

前面鋪墊了這么多終于談到有關(guān)于 Pandas 鏈?zhǔn)秸{(diào)用部分

Pandas 中的大部分方法都很適合使用鏈?zhǔn)椒椒ㄟM行操作,因為經(jīng)過 API 處理后返回的往往還是 Series 類型或 DataFrame 類型,所以我們可以直接就調(diào)用相應(yīng)的方法,這里我以我在今年 2 月份左右給別人做案例演示時爬取到的華農(nóng)兄弟 B 站視頻數(shù)據(jù)為例??梢酝ㄟ^鏈接進行獲取。

數(shù)據(jù)字段信息如下所示,里面有 300 條數(shù)據(jù),并且 20 個字段:

字段信息

但在使用這部分?jǐn)?shù)據(jù)之前,我們還需要對這部分?jǐn)?shù)據(jù)進行初步的清洗,這里我主要選取了以下字段:

  •  aid:視頻對應(yīng)的 av 號
  •  comment:評論數(shù)
  •  play:播放量
  •  title:標(biāo)題
  •  video_review:彈幕數(shù)
  •  created:上傳日期
  •  length:視頻時長

1、數(shù)據(jù)清洗

各字段對應(yīng)的值如下所示:

字段值

從數(shù)據(jù)中我們可以看到:

  1.  title 字段前面都會帶有「華農(nóng)兄弟」四個字,如果對標(biāo)題字?jǐn)?shù)進行統(tǒng)計時需要預(yù)先去除;
  2.  created 上傳日期似乎顯示成了一長串的數(shù)值,但其實是從 1970 至今的時間戳,我們需要處理成可讀懂的年月日形式;
  3.  length 播放量長度只顯示了分秒,但是小時并未用「00」來進行補全,因此這里我們一方面需要將其補全,另一方面要將其轉(zhuǎn)換成對應(yīng)的時間格式

鏈?zhǔn)秸{(diào)用操作如下:

 
 
 
 
  1. import re 
  2. import pandas as pd 
  3. # 定義字?jǐn)?shù)統(tǒng)計函數(shù)
  4. def word_count(text): 
  5.     return len(re.findall(r"[\u4e00-\u9fa5]", text)) 
  6. tidy_data = ( 
  7.     pd.read_csv('~/Desktop/huanong.csv') 
  8.         .loc[:, ['aid', 'title', 'created', 'length',  
  9.                  'play', 'comment', 'video_review']] 
  10.         .assign(title = lambda df: df['title'].str.replace("華農(nóng)兄弟:", ""),  
  11.                 title_count = lambda df: df['title'].apply(word_count), 
  12.                 created = lambda df: df['created'].pipe(pd.to_datetime, unit='s'),  
  13.                 created_date = lambda df: df['created'].dt.date, 
  14.                 length = lambda df: "00:" + df['length'], 
  15.                 video_length = lambda df: df['length'].pipe(pd.to_timedelta).dt.seconds 
  16.                 ) 
  17. )

這里首先是通過loc方法挑出其中的列,然后調(diào)用assign方法來創(chuàng)建新的字段,新的字段其字段名如果和原來的字段相一致,那么就會進行覆蓋,從assign中我們可以很清楚地看到當(dāng)中字段的產(chǎn)生過程,同lambda 表達(dá)式進行交互:

1.title 和title_count:

  •  原有的title字段因為屬于字符串類型,可以直接很方便的調(diào)用str.* 方法來進行處理,這里我就直接調(diào)用當(dāng)中的replace方法將「華農(nóng)兄弟:」字符進行清洗
  •  基于清洗好的title 字段,再對該字段使用apply方法,該方法傳遞我們前面實現(xiàn)定義好的字?jǐn)?shù)統(tǒng)計的函數(shù),對每一條記錄的標(biāo)題中,對屬于\u4e00到\u9fa5這一區(qū)間內(nèi)的所有 Unicode 中文字符進行提取,并進行長度計算

2.created和created_date:

  •  對原有的created 字段調(diào)用一個pipe方法,該方法會將created 字段傳遞進pd.to_datetime 參數(shù)中,這里需要將unit時間單位設(shè)置成s秒才能顯示出正確的時間,否則仍以 Unix 時間錯的樣式顯示
  •  基于處理好的created 字段,我們可以通過其屬于datetime64 的性質(zhì)來獲取其對應(yīng)的時間,這里 Pandas 給我們提供了一個很方便的 API 方法,通過dt.*來拿到當(dāng)中的屬性值

3.length 和video_length:

  •  原有的length 字段我們直接讓字符串00:和該字段進行直接拼接,用以做下一步轉(zhuǎn)換
  •  基于完整的length時間字符串,我們再次調(diào)用pipe方法將該字段作為參數(shù)隱式傳遞到pd.to_timedelta方法中轉(zhuǎn)化,然后同理和create_date字段一樣獲取到相應(yīng)的屬性值,這里我取的是秒數(shù)。

2、播放量趨勢圖

基于前面稍作清洗后得到的tidy_data數(shù)據(jù),我們可以快速地做一個播放量走勢的探索。這里我們需要用到created這個屬于datetime64的字段為 X 軸,播放量play 字段為 Y 軸做可視化展示。

 
 
 
 
  1. # 播放量走勢 
  2. %matplotlib inline 
  3. %config InlineBackend.figure_format = 'retina' 
  4. import matplotlib.pyplot as plt 
  5. (tidy_data[['created', 'play']] 
  6.  .set_index('created') 
  7.  .resample('1M') 
  8.  .sum() 
  9.  .plot( 
  10.     kind='line', 
  11.     figsize=(16, 8),  
  12.     title='Video Play Prend(2018-2020)',  
  13.     grid=True,  
  14.     legend=False 
  15.   ) 
  16. plt.xlabel("") 
  17. plt.ylabel('The Number Of Playing')

這里我們將上傳日期和播放量兩個選出來后,需要先將created設(shè)定為索引,才能接著使用resample重采樣的方法進行聚合操作,這里我們以月為統(tǒng)計顆粒度,對每個月播放量進行加總,之后再調(diào)用plot 接口實現(xiàn)可視化。

鏈?zhǔn)秸{(diào)用的一個小技巧就是,可以利用括號作用域連續(xù)的特性使整個鏈?zhǔn)秸{(diào)用的操作不會報錯,當(dāng)然如果不喜歡這種方式也可以手動在每條操作后面追加一個\符號,所以上面的整個操作就會變成這樣:

 
 
 
 
  1. tidy_data[['created', 'play']] \ 
  2.  .set_index('created') \ 
  3.  .resample('1M') 
  4.  .sum() 
  5.  .plot( \ 
  6.     kind='line', \ 
  7.     figsize=(16, 8), \ 
  8.     title='Video Play Prend(2018-2020)', \ 
  9.     grid=True, \ 
  10.     legend=False \ 
  11.   )

但是相比于追加一對括號來說,這種尾部追加\符號的方式并不推薦,也不優(yōu)雅。

但是如果既沒有在括號作用域或未追加\ 符號,那么在運行時 Python 解釋器就會報錯。

3、鏈?zhǔn)秸{(diào)用性能

通過前兩個案例我們可以看出鏈?zhǔn)秸{(diào)用可以說是比較優(yōu)雅且快速地能實現(xiàn)一套數(shù)據(jù)操作的流程,但是鏈?zhǔn)秸{(diào)用也會因為不同的寫法而存在性能上的差異。

這里我們繼續(xù)基于前面的tidy_data操作,這里我們基于created_date 來對play、comment和video_review進行求和后的數(shù)值進一步以 10 為底作對數(shù)化。最后需要得到以下結(jié)果:

統(tǒng)計表格

寫法一:一般寫法

一般寫法

這種寫法就是基于tidy_data拷貝后進行操作,操作得到的結(jié)果會不斷地覆蓋原有的數(shù)據(jù)對象

寫法二:鏈?zhǔn)秸{(diào)用寫法

鏈?zhǔn)秸{(diào)用寫法

可以看到,鏈?zhǔn)秸{(diào)用的寫法相比于一般寫法而言會快上一點,不過由于數(shù)據(jù)量比較小,因此二者時間的差異并不大;但鏈?zhǔn)秸{(diào)用由于不需要額外的中間變量已經(jīng)覆蓋寫入步驟,在內(nèi)存開銷上會少一些。

結(jié)尾:鏈?zhǔn)秸{(diào)用的優(yōu)劣

從本文的只言片語中,你能領(lǐng)略到鏈?zhǔn)秸{(diào)用使得代碼在可讀性上大大的增強,同時以盡肯能少的代碼量去實現(xiàn)更多操作。

當(dāng)然,鏈?zhǔn)秸{(diào)用并不算是完美的,它也存在著一定缺陷。比如說當(dāng)鏈?zhǔn)秸{(diào)用的方法超過 10 步以上時,那么出錯的幾率就會大幅度提高,從而造成調(diào)試或 Debug 的困難。比如這樣:

 
 
 
 
  1. (data 
  2.   .method1(...) 
  3.   .method2(...) 
  4.   .method3(...) 
  5.   .method4(...) 
  6.   .method5(...) 
  7.   .method6(...) 
  8.   .method7(...) # Something Error 
  9.   .method8(...) 
  10.   .method9(...) 
  11.   .method10(...) 
  12.   .method11(...) 
  13. )

你只能從鏈?zhǔn)秸{(diào)用方法體中「從尾倒頭」一步一步地去重現(xiàn)發(fā)生問題的地方在哪。

因此使用鏈?zhǔn)秸{(diào)用時,一定必須要考慮以下問題:

  1.  是否需要中間變量
  2.  操作數(shù)據(jù)中的步驟是否需要分解
  3.  每次操作后的結(jié)果是否仍為 DataFrame 類型

如果不需要中間變量、步驟不需要分解且保證最后返回的就是 DataFrame 類型,那么就愉快地使用鏈?zhǔn)秸{(diào)用方法來完成你的數(shù)據(jù)流程吧!


當(dāng)前文章:5分鐘解讀Python中的鏈?zhǔn)秸{(diào)用
本文鏈接:http://m.5511xx.com/article/cdocojj.html