摘要:在此探討的是級(jí)別以下的數(shù)據(jù)之上的分析,有基于的分布式任務(wù)精度條,主要環(huán)境是下基于包的分析和特征工程任務(wù)。當(dāng)然,首先我們得載入模塊,在中使用帶的基于顯示的進(jìn)度條前,請(qǐng)務(wù)必檢查是否安裝模塊。
在具體的分析或者特征工程之中,經(jīng)常會(huì)遇到處理時(shí)間很久的問題,當(dāng)然必要的優(yōu)化是必須的。但是顯然,數(shù)據(jù)量上升,計(jì)算量過大后,處理時(shí)間是必須的此。時(shí),如果有個(gè)可以幫助您查看任務(wù)進(jìn)度的進(jìn)度條,必定可以提高你抓住處理時(shí)間去做(磨)別(洋)事(工)。當(dāng)然逐行打印是不錯(cuò)的選擇,但在Jupyter notebook/JupyterLab中,這種實(shí)踐最大的問題是,打印過多,影響整個(gè)notebook的美觀程度。
在此探討的是5GB級(jí)別以下的數(shù)據(jù)(之上的Spark分析,有基于Zipplin的分布式任務(wù)精度條),主要環(huán)境是Jupyter下基于pandas包的分析和特征工程任務(wù)。
一個(gè)極為簡(jiǎn)單的例子tqdm是基于Python的精度條模塊,里面提供了簡(jiǎn)單的代碼行進(jìn)度條和基于ipywidgets的notebook內(nèi)的進(jìn)度條。由于現(xiàn)在tqdm相關(guān)模塊還在開發(fā)階段,可能會(huì)用到一些私有對(duì)象,之后正式版中可能具體API會(huì)有所變化。
當(dāng)然,首先我們得載入模塊,在notebook中使用tqdm帶的基于Js顯示的進(jìn)度條前,請(qǐng)務(wù)必檢查是否安裝ipywidgets模塊。
from tqdm import tqdm_notebook, _tqdm_notebook _tqdm_notebook.tqdm_notebook.pandas()
其中第一行載入的兩個(gè)方法的作用分別是:
tqdm_notebook:用來(lái)包裝任何可以iterable的對(duì)象,在使用其元素進(jìn)行運(yùn)算結(jié)束后統(tǒng)計(jì)時(shí)間。
_tqdm_notebook:其中含有模塊可以處理pandas的對(duì)象。
第二行則是重載pandas里面的對(duì)象,提供可以展示精度條的方法。
下面我們可以嘗試直接使用tqdm_notebook包裹iterable對(duì)象來(lái)展示進(jìn)度條,效果如下:
a = list(range(1, 10000)) b = range(1, 10000) _ = [(lambda x: x+1)(i) for i in tqdm_notebook(a)] _ = [(lambda x: x+1)(i) for i in tqdm_notebook(b)]
當(dāng)然如果僅僅是使用range也可以使用tqdm自帶的tnrange:
from tqdm._tqdm_notebook import tnrange _ = [(lambda x: x+1)(i) for i in tnrange(1, 10000)]
效果如下:
命名和深度在一些場(chǎng)合,可能寫需要多個(gè)層級(jí)的迭代,此時(shí),我們可以通過命名每個(gè)層級(jí)的迭代器來(lái)實(shí)現(xiàn)這個(gè)個(gè)效果。使用desc參數(shù)即可:
for i in tnrange(1, 10, desc="i Loop"): for j in tnrange(1, 10000, desc="j Loop"): i+j
當(dāng)然,如果遇到Loop過多時(shí),可能會(huì)依舊出現(xiàn)打印過多的困擾。此時(shí)leave參數(shù)是一個(gè)不錯(cuò)的推薦。
for i in tqdm_notebook(range(100), desc="i-Loop"): for j in tqdm_notebook(range(10000), desc="j-Loop", leave=False): i+j多進(jìn)程的擴(kuò)展
當(dāng)然,在具體計(jì)算中,多進(jìn)程往往是經(jīng)常會(huì)需要的一類擴(kuò)展(由于Python只能基于一個(gè)運(yùn)算核心進(jìn)行計(jì)算的限制),這時(shí)候線程的運(yùn)算也是經(jīng)常需要考量的方式。
在使用過程中,第一個(gè)需要注意的問題是,tqdm每次是在從iterable對(duì)象中取值時(shí),進(jìn)行更新,而如果在map之前的list中做進(jìn)度條的包裹,是在未使用map的函數(shù)之前統(tǒng)計(jì)。所以在進(jìn)度條完成時(shí),可能還會(huì)有一段時(shí)間后才真的執(zhí)行結(jié)束。
from multiprocessing import Pool def f(x): return x**32 p = Pool(5) _ = [i for i in p.imap(f, tnrange(1000))]
而一個(gè)更好的處理是在使用后標(biāo)記時(shí)間,使用multiprocessing.Pool.imap作為迭代對(duì)象,但這個(gè)問題是tqdm無(wú)法識(shí)別具體數(shù)量,此時(shí),指定tqdm的迭代次數(shù)total即可。
_ = [i+1 for i in tqdm_notebook(p.imap(f, range(1000)))]
_ = [i for i in tqdm_notebook(p.imap(f, range(3, 1000)), total=997)]pandas中使用
pandas中的使用,也是非常簡(jiǎn)單,在重載命令執(zhí)行后,Serires、DataFrame、GroupBy對(duì)象都會(huì)擁有progress_apply方法,用法和apply一致,直接可以調(diào)取進(jìn)度條。
實(shí)戰(zhàn):復(fù)雜場(chǎng)景中的使用最后,我們結(jié)合一下之前的多線程和pandas操作,處理更大規(guī)模的數(shù)據(jù)。基本思路是,將DataFrame拆成若干組分,最后通過pandas.concat合并起結(jié)果。
def parallelize_dataframe(df, func, n_jobs=3, split_num=10): ## 拆分?jǐn)?shù)據(jù)表 df_split = np.array_split(df, split_num) pool = Pool(n_jobs) df_list = [] ## map操作 for df_element in tqdm_notebook(pool.imap(func, df_split), total=10000): df_list.append(df_element) ## reduce操作 df = pd.concat(df_list) ## 關(guān)閉進(jìn)程 pool.close() pool.join() return df
以上實(shí)現(xiàn)了基本的基于tqdm顯示處理進(jìn)度的操作。使用方法如下:
def apply_add_1(df): return df.apply(lambda row: row["sepal_length"]+1, axis=1) _ = parallelize_dataframe(iris_df, apply_add_1)結(jié)語(yǔ)
查看了一下進(jìn)度條,這次預(yù)處理我還要花一小時(shí),可以先去沖杯咖啡了。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/42246.html