您好,登錄后才能下訂單哦!
esproc
A | |
1 | =now() |
2 | =file("C:\\Users\\Sean\\Desktop\\kaggle_data\\music_project_data\\sales.csv").import@t() |
3 | =A2.groups(year(ORDERDATE):y,month(ORDERDATE):m;sum(AMOUNT):x) |
4 | =A3.sort(m) |
5 | =A4.derive(if(m==m[-1],x/x[-1] ? -1,null):yoy) |
6 | =interval@ms(A1,now()) |
A3:用ORDERDATE的年份和月份分組,并將該列命名為y,m,同時計算該組的銷售量
group()函數分組但不匯總,groups分組同時匯總。
A4:按照月份m進行排序
A5:新增一列,如果月份等于前一行的月份,則計算增長比并賦值,否則賦值null,將該列命名為yoy。
python:
import time
import numpy as np
import pandas as pd
s = time.time()
sales = pd.read_csv("C:\\Users\\Sean\\Desktop\\kaggle_data\\music_project_data\\sales.csv",sep='\t')
sales['ORDERDATE']=pd.to_datetime(sales['ORDERDATE'])
sales['y']=sales['ORDERDATE'].dt.year
sales['m']=sales['ORDERDATE'].dt.month
sales_g = sales[['y','m','AMOUNT']].groupby(by=['y','m'],as_index=False)
amount_df = sales_g.sum().sort_values(['m','y'])
yoy = np.zeros(amount_df.values.shape[0])
yoy=(amount_df['AMOUNT']-amount_df['AMOUNT'].shift(1))/amount_df['AMOUNT'].shift(1)
yoy[amount_df['m'].shift(1)!=amount_df['m']]=np.nan
amount_df['yoy']=yoy
print(amount_df)
e = time.time()
print(e-s)
pd.to_datetime(),轉換為日期格式。新增加y和m列表示年和月。df.groupby(by,as_index)按照某個字段或者某幾個字段進行分組,其中參數as_index=False是否返回以組標簽為索引的對象。df.sort_values()將新的dataframe按照月份和年份進行分組.新建一個數組,準備存放計算出來的同期增長比。df.shift(1)表示將原來的df下一行,即相對于當前行為上一行,給該數組賦值為增長比(當前行減上一行的值除以上一行的值),由于月份不同,所以將上一行與該行相同的月份賦值為nan,最后將該數組賦值給df新增加的列yoy。
結果:
esproc
python
耗時 | |
esproc | 0.007 |
python | 0.030 |
?
esproc?????????????????????
A | |
1 | =now() |
2 | =file("E:\\esproc\\esProc\\demo\\zh\\txt\\Contract.txt").import@t() |
3 | =file("E:\\esproc\\esProc\\demo\\zh\\txt\\Client.txt").import@t().keys(ID).index() |
4 | =A2.select(year(SellDate)==1998) |
5 | =A4.groups(Client;sum(Amount):Amount) |
6 | =A5.sort(-Amount) |
7 | =A5.sum(Amount)/2 |
8 | =0 |
9 | =A6.pselect((A8=A8+Amount)>=A7) |
10 | =A3.find@k(A6.to(A9).(Client)).(Name) |
11 | =interval@ms(A1,now()) |
A3:T.keys(Ki,…),為內表T定義鍵Ki,…。;T.index(n),為序表T的鍵建立長為n的索引表,n為0或序表重置鍵時將清除索引表;n省略則自動選長度。如果需要多次根據鍵來查找數據,在建立了索引表之后可以提高效率。建立索引時假定記錄的主鍵唯一,否則出錯。
A4:篩選出1998年的交易記錄
A5:按照Client進行分組,同時計算交易量Amount之和
A6:按照Amount進行排序
A9:找到Amount累加到一半交易量的位置
A10:A.find(k),從排列/序表A中找到主鍵等于k的成員,有索引表則使用索引表。@k當參數k是序列時被認為是鍵值序列,返回鍵值對應的A的成員。這里是返回鍵ID的值等于A6.to(A9).(Client)的成員的Name字段序列。
python:
import time
import pandas as pd
import numpy as np
s = time.time()
contract_info=pd.read_csv('E:\\esproc\\esProc\\demo\\zh\\txt\\Contract.txt',sep='\t')
client_info = pd.read_csv('E:\\esproc\\esProc\\demo\\zh\\txt\\Client.txt',sep='\t',encoding='gbk')
contract_info['SellDate']=pd.to_datetime(contract_info['SellDate'])
contract_info_1998 = contract_info[contract_info['SellDate'].dt.year==1998]
contract_1998_g = contract_info_1998[['Client','Amount']].groupby(by='Client',as_index=False)
contract_sort = contract_1998_g.sum().sort_values(by = 'Amount',ascending=False).reset_index(drop=True)
half_amount = contract_sort['Amount'].sum()/2
sm=0
for i in range(len(contract_sort['Amount'])):
??? sm+=contract_sort['Amount'][i]
??? if sm>=half_amount:
??????? break
n_client = contract_sort['Client'].loc[:i]
client_info = client_info.set_index('ID')
print(client_info.loc[n_client]['Name'])
e = time.time()
print(e-s)
篩選出1998年的記錄
因為這里只用到了交易信息的Client和Amount字段,所以只選出這兩個字段并按照Client字段分組。df.sort_values(by,ascending),這里是按照Amount進行倒序排序。
df.reset_index(drop)重建索引,drop=True表示丟掉原來的索引,否則把原來的索引當做一列插入。
求得所有交易額的一半的值,循環Amount字段,找到累加之和大于或等于交易額一半的位置。取Client字段0到該位置的值組成一個Series。
根據這個Series去client_info中找到對應的行的Name值。
結果:
esproc
python
?
耗時 | |
esproc | 0.007 |
python | 0.016 |
?
esproc
A | |
1 | =now() |
2 | =file("E:\\esproc\\esProc\\demo\\zh\\txt\\SalesRecord.txt").import@t() |
3 | =A2.groups(clerk_name:name,month(sale_date):month;sum(sale_amt):amount) |
4 | =A3.group(month) |
5 | =A4.(~.sort(-amount).to(8)) |
6 | =A5.isect(~.(name)) |
7 | =interval@ms(A1,now()) |
A3:按照clerk_name和月份month(sale_date)分組,同時將這兩個字段命名為name和month,計算各組sale_amt的和,命名為amount
A4:按照月份分組并進行求和。
A5:將amount按照倒序排序,并取前8名
A6: A.isect(),序列A成員可以為序列,產生所有子序列都有的成員組成的新序列。這里是求所有成員的交集。
python:
import time
import pandas as pd
import numpy as np
s = time.time()
sale_rec = pd.read_csv('E:\\esproc\\esProc\\demo\\zh\\txt\\SalesRecord.txt',sep='\t')
sale_rec['sale_date'] = pd.to_datetime(sale_rec['sale_date'])
sale_rec['m'] = sale_rec['sale_date'].dt.month
sale_rec_g = sale_rec.groupby(by=['clerk_name','m'],as_index=False).sum()
sale_month_g = sale_rec_g.groupby('m',as_index=False)
sale_set = set(sale_rec['clerk_name'].drop_duplicates().values.tolist())
for index,group in sale_month_g:
??? group_topn = group.sort_values(by='sale_amt',ascending=False)[:8]
??? sale_set = sale_set.intersection(set(group_topn['clerk_name'].values.tolist()))
print(list(sale_set))?????
e = time.time()
print(e-s)
新增一列m表示月份
按照clerk_name,m進行分組,并求取sale_amt的和
按照m分組
初始化一個包含所有clerk_name的集合
循環分組,用初始集合與各個組的clerk_name一次求交集,并賦值給初始的集合,最終求得所有集合的交集。
結果:
結果 | 耗時 | |
esproc | Jenny,Steven | 0.010 |
python | Jenny,Steven | 0.023 |
?
esproc
A | |
1 | =now() |
2 | =file("C:\\Users\\Sean\\Desktop\\kaggle_data\\music_project_data\\old.csv").import@t() |
3 | =file("C:\\Users\\Sean\\Desktop\\kaggle_data\\music_project_data\\new.csv").import@t() |
4 | =A2.sort(userName,date) |
5 | =A3.sort(userName,date) |
6 | =[A5,A4].merge@d(userName,date) |
7 | =[A4,A5].merge@d(userName,date) |
8 | =[A5,A4].merge@d(userName,date,saleValue,saleCount) |
9 | =[A8,A6].merge@d(userName,date) |
10 | =interval@ms(A1,now()) |
A4、A5:按照userName和date排序
A6: A.merge(xi,…) ,歸并計算A(i)|…,A(i)對[xi,…]有序,將多個序表/排列按指定字段xi有序合并,xi省略按主鍵合并,若xi省略且A沒有主鍵則按照r.v()合并。A(i)必須同構。@d選項,從A(1)中去掉A(2)?&…A(n)中的成員后形成的新序表/排列,即求差集。新表與舊表的差集即新增加的記錄。
A7:求舊表與新表的差集,即舊表中刪除的記錄。
A8:xi為所有字段,得到新表中所有修改過的記錄包括新增的和修改的
A9:用所有修改的記錄與新增的記錄求差集得到修改的記錄。
python:
import time
import pandas as pd
import numpy as np
s = time.time()
old = pd.read_csv('C:\\Users\\Sean\\Desktop\\kaggle_data\\music_project_data\\old.csv',sep='\t')
new = pd.read_csv('C:\\Users\\Sean\\Desktop\\kaggle_data\\music_project_data\\new.csv',sep='\t')
old_delet_rec = pd.merge(old,new,how='left',on=['userName','date'])
delet_rec = old_delet_rec[np.isnan(old_delet_rec['saleValue_y'])][['userName', 'date', 'saleValue_x', 'saleCount_x']]
print('delet_rec')
print(delet_rec)
new_add_rec =? pd.merge(old,new,how='right',on=['userName','date'])
new_rec = new_add_rec[np.isnan(new_add_rec['saleValue_x'])][['userName', 'date', 'saleValue_y', 'saleCount_y']]
print('new_rec')
print(new_rec)
all_rec = pd.concat([old,new])
all_update_rec = all_rec.drop_duplicates(keep=False)
update_rec = all_update_rec[all_update_rec[['userName','date']].duplicated()]
print('update_rec')
print(update_rec)
e = time.time()
print(e-s)
首先merge(old,new,on=’left’)將舊表左連接新表,新表中包含nan的行就是舊表刪除的行,由于字段名一樣,所以python默認添加的后綴是_x,_y,刪除的記錄就是截取merge以后的前四個字段。
同理使用右連接,得到新表新增的行。
pd.concat([df1,df2])將舊表和新表縱向連接,df.drop_duplicates(keep=False),刪除所有重復的行,得到兩張表所有不一樣的記錄,從中選出['userName','date']兩個字段相同的字段,即為修改過的字段。
結果:
esproc
delet_rec
new_rec
update_rec
python
耗時 | |
esproc | 0.003 |
python | 0.038 |
?
題目介紹:stocklog.csv中的數據有四個字段分別是STOCKID貨物編號,DATE日期(不連續),QUANTITY出入庫數量,INDICATOR標致,如果INDICATOR為空表示入庫,ISSUE表示出庫。
數據如下:
我們的目的是用這份數據分別計算出指定時間內各種貨物的庫存狀態,即STOCKID,貨物編號,DATE日期(連續的),OPEN開庫時數量,ENTER當天入庫數量,TOTAL最當天最大數量,ISSUE當天出庫數量,CLOSE閉庫時的數量。
esproc
A | B | |
1 | =now() | |
2 | =file("C:\\Users\\Sean\\Desktop\\kaggle_data\\music_project_data\\stocklog.csv").import@t() | |
3 | =A2.select(DATE>=date(start) ? && DATE<=date(end)) | |
4 | =A3.groups(STOCKID,DATE;sum(if(INDICATOR=="ISSUE",QUANTITY,0)):ISSUE,sum(if(INDICATOR!="ISSUE",QUANTITY,0)):ENTER) | |
5 | =periods(start,end) | |
6 | for ? A4.group(STOCKID) | =A6.align(A5,DATE) |
7 | >b=c=0 | |
8 | =B6.new(A6.STOCKID:STOCKID,A5(#):DATE,c:OPEN,ENTER,(b=c+ENTER):TOTAL,ISSUE,(c=b-ISSUE):CLOSE) | |
9 | >B8.run(ENTER=ifn(ENTER,0),ISSUE=ifn(ISSUE,0)) | |
10 | =@|B8 | |
11 | =interval@ms(A1,now()) |
A3:選出指定日期內的數據,start和end是提前設置好的網格變量(在集算器的程序——網格參數處可以設置。)
A4:按照STOCKID和DATE分組,同時對各組進行計算,if(x,true,false),這里是如果INDICATOR==ISSUE,if()函數等于QUANTITY的值,否則為0,將此結果在該組中求和后添加到字段ISSUE,如果INDICATOR==ISSUE,if()函數等于0,否則為QUANTITY的值,將此結果在該組中求和后添加到字段ENTER。最終得到每天每種物品的出入庫總數。
A5: periods可以生成時間序列
A6:循環分組
B6: P.align(A:x,y),x,y省略則以P當前記錄與A中成員對齊。通過關聯字段x?和?y?將P?的記錄按照A?對齊。對著排列P計算y的值,計算結果和A中的x的值相等則表示兩者對齊。這里是當前產品的出入庫記錄與B5中的時間序列對齊。
B7:定義b,c兩個變量,b作為OPEN字段的初始值,
B8:建立新表,其中STOCKID為A6的STOCKID,將時間序列B5按順序插入新序表,作為新字段DATE,c作為OPEN字段,將B6中的ENTER字段當做現在ENTER字段,為b賦值為c+ENTER作為TOTAL字段,將B6中的ISSUE字段當做現在ISSUE字段,最后把c賦值為b-ISSUE作為CLOSE字段。
B9: ifn(valueExp1, valueExp2) 判斷valueExp1的值是否為空,若為空則返回valueExp2,不為空則返回該表達式的值。這里就是將null填為0.
B10:@表示當前格,這里的意思是把結果不斷的匯總在當前格,最后得到結果。
python:
import time
import pandas as pd
import numpy as np
s=time.time()
starttime = '2015-01-01'
endtime = '2015-12-31'
stock_data = pd.read_csv('C:\\Users\\Sean\\Desktop\\kaggle_data\\music_project_data\\stocklog.csv',sep='\t')
stock_data['DATE']=pd.to_datetime(stock_data['DATE'])
stock_data = stock_data[stock_data['DATE']>=starttime]
stock_data = stock_data[stock_data['DATE']<=endtime]
stock_data['ENTER']=stock_data['QUANTITY'][stock_data['INDICATOR']!='ISSUE']
stock_data['ISSUE']=stock_data['QUANTITY'][stock_data['INDICATOR']=='ISSUE']
stock_g = stock_data[['STOCKID','DATE','ENTER','ISSUE']].groupby(by=['STOCKID','DATE'],as_index=False).sum()
stock_gr = stock_g.groupby(by='STOCKID',as_index = False)
date_df = pd.DataFrame(pd.date_range(starttime,endtime),columns=['DATE'])
stock_status_list = []
for index,group in stock_gr:
??? date_df['STOCKID']=group['STOCKID'].values[0]
??? stock_status = pd.merge(date_df,group,on=['STOCKID','DATE'],how='left')
??? stock_status = stock_status.sort_values(['STOCKID','DATE'])
??? stock_status['OPEN']=0
??? stock_status['CLOSE']=0
??? stock_status['TOTAL']=0
??? stock_status = stock_status.fillna(0)
??? stock_value = stock_status[['STOCKID','DATE','OPEN','ENTER','TOTAL','ISSUE','CLOSE']].values
??? open = 0
??? for value in stock_value:
??????? value[2] = open
??????? value[4] = value[2]+value[3]
??????? value[6] = value[4] - value[5]
??????? open = value[6]
??? stock = pd.DataFrame(stock_value,columns = ['STOCKID','DATE','OPEN','ENTER','TOTAL','ISSUE','CLOSE'])
??? stock_status_list.append(stock)
stock_status = pd.concat(stock_status_list,ignore_index=True)
print(stock_status)
e=time.time()
print(e-s)
pd.to_datetime(),將DATE字段轉換為pandas的datetime類型。Pandas寫成這種形式(stock_data = stock_data[endtime>=stock_data['DATE']>=starttime])進行日期篩選是會報錯的,不支持同時計算,所以只能分兩次截取時間。
新建ENTER,ISSUE兩個字段,并按照INDICATOR是否是ISSUE判斷,如果是則將QUANTITY的值賦值給ISSUE,如果不是則將QUANTITY的值賦值給ENTER。
取到STOCKID,DATE,ENTER,ISSUE四個字段,并按照STOCKID,DATE進行分組,同時對各組求和,得到每一天每種貨物的出入庫記錄。
pd.date_range(starttime,endtime)生成一個starttime~endtime的Series,pd.DataFrame()將它生成為一個dataframe(date_df)
將數據按照STOCKID進行分組
新建一個list,準備加入各個貨物的出入庫狀態。
循環各組,為 date_df加入STOCKID列,生成包含DATE,STOCKID兩列的dataframe,pd.merge(df1,df2,on,how),將該dataframe與該組按照STOCKID,DATE,進行左連接,得到連續日期。
df.fillna(0)將df中的nan賦值為0,
新增加三列OPEN,TOTAL,CLOSE并都賦值為0.
將字段按照['STOCKID','DATE','OPEN','ENTER','TOTAL','ISSUE','CLOSE']順序,依次取出,并取得這些字段的值(類型是numpy.ndarray)。
初始化open=0
循環這個數組中的元素,'OPEN','ENTER','TOTAL','ISSUE','CLOSE'字段對應的值分別為value[2], value[3], value[4], value[5], value[6],open賦值給value[2],TOTAL=OPEN+ENTER,CLOSE=TOTAL-ISSUE,再將close賦值給open作為下一元素的value[2]。
最后將該數組轉換為dataframe,得到這種貨物的出入庫狀態
將所有貨物的出入庫狀態都放入開始新建的list中
最后pd.concat([df1,df2,…,dfn],ignore_index)合并這些dataframe,忽略原來的索引,得到所有貨物的出入庫狀態。
結果:
esproc
python
耗時 | |
esproc | 0.015 |
python | 0.089 |
?
題目介紹:表duty記錄著值班情況,一個人通常會持續值班幾個工作日再換其他人,數據如下:
我們的目的是根據duty表計算出每個值班的起止時間。
esproc
A | |
1 | =now() |
2 | =file("C:\\Users\\Sean\\Desktop\\kaggle_data\\music_project_data\\duty.csv").import@t() |
3 | =A2.group@o(name) |
4 | =A3.new(name,~.m(1).date:begin,~.m(-1).date:end) |
5 | =interval@ms(A1,now()) |
本例依舊簡單
A3:A.group(xi,…),將序列/排列按照一個或多個字段/表達式進行等值分組,結果為組集構成的序列。@o表示分組時不重新排序,數據變化時才另分一組。
A4:A.new()根據序表/排列A的長度,生成一個記錄數和A相同,且每條記錄的字段值為xi,字段名為Fi的新序表/排列。這里表示根據分組子集A3新建二維表,其中~.m(1)表示取各組首行,~.m(-1)表示取各組尾行。
python:
import time
import pandas as pd
import numpy as np
import random
s=time.time()
duty = pd.read_csv('C:\\Users\\Sean\\Desktop\\kaggle_data\\music_project_data\\duty.csv',sep='\t')
name_rec = ''
start = 0
duty_list = []
for i in range(len(duty)):
??? if name_rec == '':
??????? name_rec = duty['name'][i]
??? if name_rec != duty['name'][i]:
??????? begin = duty['date'].loc[start:i-1].values[0]
??????? end = duty['date'].loc[start:i-1].values[-1]
??????? duty_list.append([name_rec,begin,end])
??????? start = i
??????? name_rec = duty['name'][i]
begin = duty['date'].loc[start:i].values[0]
end = duty['date'].loc[start:i].values[-1]
duty_list.append([name_rec,begin,end])
duty_b_e = pd.DataFrame(duty_list,columns=['name','begin','end'])
print(duty_b_e)
e=time.time()
print(e-s)
說明:小編沒有找到pandas中不重新排序進行分組的方法,所以只能選擇這種笨方法,又因為一直都是對比的pandas,所以也沒有用python自帶的IO讀取方式來完成此題。下面還是簡單介紹下代碼:
初始化name_rec用來保留name字段的值,strat用來保留截取位置,duty_list用來保存最后的結果。
創建一個循環,開始將數據中的第一個name的值賦值給name_rec,然后下一次循環,如果name_rec相同,則繼續。直到不相同了,取start~i-1位置的date的值,第0個賦值給begin,倒數第一個賦值給end,將name_rec,begin,end三個值放入初始化的duty_list中,然后將start賦值為i緩存下來,更新name_rec為當前的name值,進行下一次循環。
利用pd.DataFrame()生成dataframe。
結果:
esproc
python
耗時 | |
esproc | 0.003 |
python | 0.020 |
?
題目介紹:sports表中存放有各個項目(短跑,長跑,跳遠,跳高,鉛球)的成績(優秀,良好,及格,不及格),數據如下
我們的目的是統計出各個等級在各個項目上的人數。
esproc
A | B | |
1 | =now() | |
2 | =file("C:\\Users\\Sean\\Desktop\\kaggle_data\\music_project_data\\sports.csv").import@t() | |
3 | =[] | |
4 | for ? A2.fname().to(2,) | =A2.group(${A4}) |
5 | =B4.new(A4:subject,~.${A4}:mark,~.count():count) | |
6 | >A3=A3|B5 | |
7 | =A3.pivot(subject;mark,count) | |
8 | =interval@ms(A1,now()) |
A3:初始化一個空序列,用來匯總統計的結果
A4:因為sports表第一個字段是name,所以不用循環。循環各個項目的字段
B4:按照循環的這個字段進行分組
B5:新建一個表,該字段名作為subject字段的值,該字段分組中的值作為mark字段,分組中的成員數作為count字段
B6:將每個項目的結果匯總到A3中
A7: A.pivot(g,…;F,V;Ni:N'i,…),以字段/表達式g為組,將每組中的以F和V為字段列的數據轉換成以Ni和N'i為字段列的數據,以實現行和列的轉換。Ni缺省為F中的不重復字段值,N'i缺省為Ni。實現行列轉換,形成透視表。
python:
import time
import pandas as pd
import numpy as np
s = time.time()
sports = pd.read_csv('C:\\Users\\Sean\\Desktop\\kaggle_data\\music_project_data\\sports.csv',sep='\t')
subject_mark_cnt_list = []
for col in sports.columns[1:]:
??? sports_g = sports.groupby(by=col,as_index=False).count()[[col,'name']]
??? sports_g.rename(columns={'name':'count',col:'mark'},inplace=True)
??? sports_g['subject']=col
??? subject_mark_cnt_list.append(sports_g)
subject_mark_cnt = pd.concat(subject_mark_cnt_list,ignore_index=True)
subject_mark_count = pd.pivot_table(subject_mark_cnt[['subject','mark','count']],index = ['subject'],columns = 'mark',values = 'count')
print(subject_mark_count)
e = time.time()
print(e-s)
初始化subject_mark_cnt_list準備匯總循環的結果
循環除第一個字段的所有字段
df.groupby()按照該字段進行分組,統計分組中的成員數量,同時取當前的col這個字段和name字段。
df.rename(columns={})修改這個dataframe的列名
新增一列subject,并賦值為當前的col值。
將這個dataframe放入初始化的subject_mark_cnt_list列表中。
pd.concat()將列表中的數據連接成新的dataframe
pd.pivot_table(data,index,columns,values)將其改為透視表。
結果:
esproc
python
耗時 | |
esproc | 0.004 |
python | 0.083 |
?
小結:本節我們計算了一些網上常見的題目,這些題目中多次用到了動態計算字段值,并進行賦值的操作,esproc很好的支持這一功能,大大簡化了代碼。而python不支持此功能,帶來了麻煩,并且esproc的~表示了當前記錄,省去了循環語句(其實仍是循環),python只能通過循環來完成。另外python中的merge函數不支持差集計算(或許其他函數支持),造成在第四例中特別麻煩。python pandas的dataframe結構是按列進行存儲的,按行循環時就顯得特別麻煩。
sales.csv
Contract.txt
Client.txt
SalesRecord.txt
old.csv
new.csv
stocklog.csv
duty.csv
sports.csv
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。