這些讓人相見(jiàn)恨晚的高效代碼小技巧你聽(tīng)過(guò)嗎?
本文轉(zhuǎn)載自公眾號(hào)“讀芯術(shù)”(ID:AI_Discovery)
Python出圈了,似乎現(xiàn)在人人都在學(xué)Python,朋友圈的課程廣告遍地跑,小學(xué)生都看起了編程入門(mén)。的確,Python是目前公認(rèn)的最通用的編程語(yǔ)言,以其易理解易操作的優(yōu)勢(shì)攻占了每一個(gè)職場(chǎng)人大學(xué)生必備技能榜單。
學(xué)會(huì)Python確實(shí)能協(xié)助你高效工作。但學(xué)了是一回事兒,會(huì)了是另一回事兒,不是每個(gè)人學(xué)過(guò)Python的人都能玩得轉(zhuǎn)它。以下幾個(gè)小技巧,能讓你離玩轉(zhuǎn)Python更進(jìn)一步。
把不常用的類(lèi)別整合成一個(gè)
有時(shí)你會(huì)得到元素分布不均的欄,少有的類(lèi)別也是僅僅存在而已。通常會(huì)希望能將這些類(lèi)別合并為一個(gè)。
- df.artists.value_counts()
要將Coldplay和Weekend合并到一個(gè)類(lèi)別中,因?yàn)樗鼈儗?duì)數(shù)據(jù)集的影響微乎其微。該怎么做?
首先,找到不想改變的元素,比如Eminem,TaylorSwift和BrunoMars:
- myList =df.artists.value_counts().nlargest(3).index
使用where()函數(shù)替換其他元素
- dfdf_new = df.where(df.artists.isin(myList),other='otherartists')
- df_new.artists.value_counts()
這便是按要求修改后的更新列。
查找列表的新元素
給定兩個(gè)不同的列表,要求找到一個(gè)列表中有但另一個(gè)列表中沒(méi)有的元素時(shí),參照這兩個(gè)列表:
- A = [ 1, 3, 5, 7, 9 ]
- B = [ 4, 5, 6, 7, 8 ]
為了找到列表A中的新元素,我們?nèi)×斜鞟與列表B的集合差:
- set(A) - set(B)
值1、3和9只出現(xiàn)在列表A而不出現(xiàn)在列表B中。
擺脫警告
運(yùn)行代碼時(shí),經(jīng)常會(huì)收到很多警告。沒(méi)過(guò)多久它就開(kāi)始使人惱火。例如每當(dāng)導(dǎo)入朝代時(shí),可能會(huì)收到警告(FutureWarning)消息
可以用下述代碼隱藏所有警告。請(qǐng)確保其寫(xiě)在代碼頂部。
- import warnings
- warnings.filterwarnings(action='ignore')
- import keras
這將有助于在整個(gè)代碼中隱藏所有警告。
Map() 函數(shù)
map()函數(shù)接受函數(shù)(function)和序列(iterable)兩個(gè)參數(shù),返回包含結(jié)果的映射:
- map(func,itr)
func 是指接收來(lái)自映射傳遞的給定序列元素的函數(shù)。
itr是指可以被映射的序列。
- def product(n1,n2):
- return n1 *n2 list1 = (1, 2, 3, 4)
- list2 = (10,20,30,40)result = map(product, list1,list2)
- list(result)
開(kāi)始解碼。
Product函數(shù)接受兩個(gè)列表,并反饋兩個(gè)列表的乘積。列表1和列表2是充當(dāng)map函數(shù)序列的兩個(gè)列表。map()集product函數(shù)和序列于一身→列表1和列表2,以及反饋兩個(gè)列表的乘積作為結(jié)果。
Map + Lambda組合
可以使用lambda表達(dá)式修改上述代碼,以替換product函數(shù):
- list1 = (1, 2, 3, 4)
- list2 = (10,20,30,40)
- result = map(lambda x,y: x * y, list1,list2)
- print(list(result))
Lambda表達(dá)式有助于降低單獨(dú)編寫(xiě)函數(shù)的成本。
啟動(dòng)、停止和設(shè)置
Slice(start:stop[:step])是通常包含部分序列的對(duì)象。
- 如果只提供停止,則從索引0開(kāi)始生成部分序列直到停止。
- 如果只提供開(kāi)始,則在索引開(kāi)始之后生成部分序列直到最后一個(gè)元素。
- 如果同時(shí)提供開(kāi)始和停止,則在索引開(kāi)始之后生成部分序列直到停止。
- 如果起始、停止和步驟三者同時(shí)提供,則在索引開(kāi)始之后生成部分序列直到停止,并增加索引步驟。
- x = [ 1, 2, 3, 4, 5, 6, 7, 8 ]
- x[ 1: 6: 2]
上面的代碼中,1是開(kāi)始索引,6是停止索引,2是步驟索引。這意味著從指數(shù)1開(kāi)始到指數(shù)6停止,步長(zhǎng)為2。
還可以使用[::-1]操作翻轉(zhuǎn)列表:
- x[::-1]
沒(méi)錯(cuò),通過(guò)開(kāi)始、停止和步驟操作,很容易就可以將整個(gè)列表進(jìn)行逆轉(zhuǎn)。
組合Zip和Enumerate
zip和enumerate函數(shù)常用于for循環(huán),兩個(gè)一起用就更精彩了。它不僅可以在單個(gè)循環(huán)中迭代多個(gè)值,而且可以同時(shí)獲得索引。
- NAME = ['Sid','John','David']
- BIRD = ['Eagle','Sparrow','Vulture']
- CITY =['Mumbai','US','London']for i,(name,bird,city) inenumerate(zip(NAME,BIRD,CITY)):
- print(i,' represents ',name,' ,',bird,' and ',city)
Zip函數(shù)可以將所有列表合并為一個(gè),以便同時(shí)訪(fǎng)問(wèn)每個(gè)列表,而Enumerate函數(shù)協(xié)助獲得索引以及附加到該索引的元素。
隨機(jī)抽樣
有時(shí)會(huì)遇到非常大的數(shù)據(jù)集,因而決定處理數(shù)據(jù)的隨機(jī)子集。pandas數(shù)據(jù)框的sample函數(shù)可以實(shí)現(xiàn)更多的功能。不妨看看在上面已經(jīng)創(chuàng)建過(guò)的歌星數(shù)據(jù)模型。
- df.sample(n=10)
這有助于獲取數(shù)據(jù)集里隨機(jī)的10行。
- df.sample(frac=0.5).reset_index(drop=True)
分解上面的代碼,frac參數(shù)取值在0到1之間,包括1。它占用分配給它的數(shù)據(jù)流的一部分。在上面的代碼片段中指定了0.5,因此它將返回size→0.5*的隨機(jī)子集
你能看到前面的reset_index函數(shù)。它有助于適當(dāng)?shù)刂嘏潘饕驗(yàn)楂@取隨機(jī)子集時(shí),索引也會(huì)被重新排列。
保留內(nèi)存
隨著編程的深入,你將意識(shí)到記住內(nèi)存高效代碼的重要性。生成器是返回我們可以遍歷的對(duì)象的函數(shù)。這有助于有效利用內(nèi)存,因此它主要用于當(dāng)在無(wú)限長(zhǎng)的序列上迭代。
- def SampleGenerator(n):
- yield n
- nn = n+1
- yield n
- nn = n+1
- yield ngen = SampleGenerator(1)
Yield 語(yǔ)句暫停函數(shù),保存其所有狀態(tài),并在以后的連續(xù)調(diào)用中繼續(xù)執(zhí)行。
- print(next(gen))
- print(next(gen))
- print(next(gen))
如你所見(jiàn),yield保存了前一個(gè)狀態(tài),而每當(dāng)我們調(diào)用下一個(gè)函數(shù)時(shí),它都會(huì)繼續(xù)到下一個(gè)返回其新輸出的yield。
通過(guò)添加在generator函數(shù)內(nèi)無(wú)限運(yùn)行的while循環(huán),可以迭代單個(gè)yield。
- def updatedGenerator(n):
- while(1):
- yield n
- nn = n + 1
- a = updatedGenerator(1)for i in range(5):
- print(next(a))
While語(yǔ)句可以反復(fù)迭代相同的yield語(yǔ)句。
救世主Skiprows
重頭戲壓軸出場(chǎng)!要讀取的csv文件過(guò)大,以至于內(nèi)存不夠用?Skiprows可以輕松解決。
圖源:unsplash
它可以指定需要在數(shù)據(jù)框中跳過(guò)的行數(shù)。
假設(shè)有個(gè)100萬(wàn)行的數(shù)據(jù)集,不適合你的內(nèi)存。如果分配skiprows=0.5 million(跳讀50萬(wàn)行),在讀取數(shù)據(jù)集的時(shí)候就會(huì)跳過(guò)50萬(wàn)行,這樣就可以輕松地讀取數(shù)據(jù)集的子集。
- df = pd.read_csv('artist.csv')
- df_new = pd.read_csv('artist.csv',skiprows=50)df.shape,
- df_new.shape
在上面的代碼片段中,df表示包含112行的數(shù)據(jù)集。在添加了skiprows=50(跳讀50行)之后,它跳過(guò)了數(shù)據(jù)集中的50行,從而讀取了62行作為新數(shù)據(jù)集。
破案啦!編碼效率提升一大截的秘密就在于此。