本節在數據量比較大的狀況下,對比esproc和python。python
數據量:7000多條萬記錄,5個字段分別是orderid,clientid,sellerid,amount,date。總大小超過3G。app
esproc測試
A2:f.cursor()spa
根據文件f建立遊標並返回,數據掃描完將自動關閉遊標。@t, f中第一行記錄做爲字段名,不使用本選項時默認使用_1,_2,…做爲字段名. @c, 無s時用逗號分隔。若是同時有s則用s分隔。線程
A3:篩選出8月份的訂單記錄並取出結果code
esproc並行代碼:對象
A2:cursor@m(;n),@m選項,返回成多路遊標,n表示路數。這時結果可能改變原來數據的順序(篩選數據大多數狀況下也不須要保持原序)。排序
python:ip
import time import pandas as pd import numpy as np s = time.time() chunksize=1000000 order_data = pd.read_csv('E:\\orders_big_data\\orders.csv',iterator=True,chunksize=chunksize) i = 0 month_8_list = [] for chunk in order_data: chunk['date'] = pd.to_datetime(chunk['date']) chunk_month_8 = chunk[chunk['date'].dt.month==8] month_8_list.append(chunk_month_8) month_8 = pd.concat(month_8_list,ignore_index=True) print(month_8) e = time.time() print(e-s)
定義chunksize大小爲1000000萬條記錄。內存
pd.read_csv(fileorbuf,iterator,chunksize) iterator,返回一個TextFileReader 對象,以便逐塊處理文件,chunksize文件塊大小。
循環讀取文件,每次都取chunksize的大小,篩選出8月份的記錄,放入初始化的list中。
合併list中的dataframe獲得結果。
pandas自己不支持並行,因此這裏沒有python的並行測試。
結果:
esproc單線程
esproc並行:
python
esproc
A2:按照sellerid和年份進行分組,同時彙總amount和count數。只取出計算須要的字段。
esproc並行代碼
python:
import time import pandas as pd import numpy as np s = time.time() chunksize=1000000 order_data = pd.read_csv('E:\\orders_big_data\\orders.csv',usecols=['sellerid','date','amount'],iterator=True,chunksize=chunksize) chunk_g_list = [] for chunk in order_data: chunk['date'] = pd.to_datetime(chunk['date']) chunk['y'] = chunk['date'].dt.year chunk_g = chunk.groupby(by=['sellerid','y']).agg(['sum','count']).reset_index() chunk_g_list.append(chunk_g) order_group = pd.concat(chunk_g_list,ignore_index=True).groupby(by=['sellerid','y'],as_index=False).agg({('amount','sum'):['sum'],('amount','count'):['sum']}) order_group.columns = ['sellerid','y','amount','count'] print(order_group) e = time.time() print(e-s)
定義chunksize爲100萬
pd.read_csv(fileorbuf,usecols,iterator,chunksize)usecols是取出須要的字段。
按照chunksize循環讀取數據
轉換date字段的格式爲pandas的datetime格式
新增一列年份y
df.groupby(by),按照sellerid和y進行分組。df.agg(),對分組數據進行多種計算。這裏是對分組數據amount進行sum和count計算。
將結果放入list中
合併list中的df,而後再按照sellerid和y分組同時計算amount的sum值,(amount,count)的sum值。
結果:
esproc和esproc並行
python
esproc
A2:遊標讀取clientid字段
A3:cs.id(x)獲取遊標cs中字段x的不一樣值造成的序列。
python:
import time import pandas as pd import numpy as np s = time.time() chunksize=1000000 order_data = pd.read_csv('E:\\orders_big_data\\orders.csv',usecols = ['clientid'],iterator=True,chunksize=chunksize) client_set = set() for chunk in order_data: client_set = client_set|set(chunk['clientid'].values) print(pd.Series(list(client_set))) e = time.time() print(e-s)
定義chunksize,100萬
pd.read_csv(),usecols參數是讀取的字段,這裏只讀取clientid字段。
定義一個集合
按照chunksize循環數據,取chunk的clientid字段的值組成集合並與原來的集合求並集,最終的集合即爲客戶的名單.
爲了便於查看將其轉成series結構
結果:
esproc
python
esproc
A3:按照sellerid分組並取amount最大的前三條記錄。A.top(n;x)存在x時,返回的是記錄。針對序列的每一個成員計算表達式x,返回前n個最小值對應的記錄。
A4:鏈接top3字段的序表組成新序表。
esproc並行代碼
python:
import time import pandas as pd import numpy as np s = time.time() chunksize=1000000 order_data = pd.read_csv('E:\\orders_big_data\\orders.csv',iterator=True,chunksize=chunksize) group_list = [] for chunk in order_data: for_inter_list = [] top_n = chunk.groupby(by='sellerid',as_index=False) for index,group in top_n: group = group.sort_values(by='amount',ascending=False).iloc[:3] for_inter_list.append(group) for_inter_df = pd.concat(for_inter_list,ignore_index=True) group_list.append(for_inter_df) top_n_gr = pd.concat(group_list,ignore_index=True).groupby(by='sellerid',as_index=False) top_n_list=[] for index,group in top_n_gr: group = group.sort_values(by='amount',ascending=False).iloc[:3] top_n_list.append(group) top_3 = pd.concat(top_n_list) print(top_3) e = time.time() print(e-s)
定義一個list,用來存放每一個chunk生成的df
循環數據
定義一個循環內的list,用來存放分組之後的df
按照sellerid分組
循環分組,按照amount排序,ascending=Falese表示倒序排序,取前三個,而後將結果放入for循環內的list中
合併循環內list的df
循環結束後,合併最初定義的list中的df
再次按照sellerid分組
循環分組,按照amount排序,ascending=Falese表示倒序排序,取前三個
合併此次獲得結果,獲得每一個銷售員銷售額最大的 3 筆訂單
結果:
esproc
python
小結:本節咱們用比較大的數據進行了簡單的計算,包括條件查詢、分組彙總、得到惟一值和topn。從代碼的複雜度和運行速度看,esproc都佔據了優點,esproc能夠輕鬆的經過並行提升運行效率,充分發揮多核cpu的優點,而python則很難作到。第四例中,python進行了屢次循環、排序、合併。我嘗試了使用python原生庫作第4例的題目,因爲一直都是對比的pandas因此這裏沒有重點介紹,運行效率比pandas快(耗時:183.164),但仍沒有esproc快,這裏僅供你們參考。python能夠根據內存的大小調節chunksize的大小,在內存容許的狀況下chunksize越大,運行效率越高。
s = time.time() seller_dic = {} with open('E:\\orders_big_data\\orders2.csv') as fd: i=0 for line in fd: if i ==0: cols = line.strip().split(',') i+=1 else: ss = line.strip().split(',') if len(ss) != 5: continue orderid = ss[0] clientid = ss[1] sellerid = int(ss[2]) amount = float(ss[3]) date = ss[4] if sellerid not in seller_dic: seller_dic[sellerid]={} seller_dic[sellerid][amount] = ss else: if len(seller_dic[sellerid])<3: seller_dic[sellerid][amount] = ss else: if amount>min(seller_dic[sellerid].keys()): seller_dic[sellerid].pop(min(seller_dic[sellerid].keys())) seller_dic[sellerid][amount]=ss seller_list = sorted(seller_dic.items(),key=lambda x:x[0]) top_3_list = [] for item in seller_list: for j in sorted(item[1].items(),key=lambda x:x[0],reverse=True): top_3_list.append(j[1]) top_3_df = pd.DataFrame(top_3_list,columns=cols) print(top_3_df) e = time.time() print(e-s)