<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          七步搞定一個綜合案例,掌握pandas進階用法!

          共 3887字,需瀏覽 8分鐘

           ·

          2021-01-25 12:24


          案例引入

          現(xiàn)有一批銷售數(shù)據(jù),如下圖所示:

          每個城市會銷售各種各樣的產品,現(xiàn)在想要統(tǒng)計每個城市各個子類別中,累計銷售數(shù)量篩選出每個城市每個子類別中銷量占比top 50%的至多3個產品。如果銷量排名前3種的產品未超過50%,則取Top3,如果超過50%,則取剛好大于50%的Top產品。輸出的結果為3列,分別為城市,子類別,產品列表(逗號隔開)。如下圖所示,①處有3種產品,是【上海-收納具】銷量Top3的產品,其銷售數(shù)量占比超過50%(或未達50%但已達到Top3,雖然這里后兩個產品都是文件夾,但觀察原始數(shù)據(jù)會發(fā)現(xiàn),這是兩種不同的文件夾);②處有兩件商品,說明【上海-桌子】中木桌,電腦桌銷量已超桌子的50%。

          案例淺析

          雖然在表述上有些繞,但其實需求還是比較明確的。仔細分析,從業(yè)務邏輯上,這里需要用到pandas的如下技巧。文件讀取-->分組求和-->分組排序-->計算各組累計百分比-->取Top3(需要與50%作比較)-->分組取列表-->文件保存。從具體實現(xiàn)上,可能還有其他處理技巧,如數(shù)據(jù)拼接(merge)等。下面結合代碼進行講解。

          案例解答

          0.必要包導入

          正式開始前,需要引入相關包,主要是pandas。為過濾異常,這里也引入了warnings包。

          import pandas as pdimport warningswarnings.filterwarnings('ignore')

          1.數(shù)據(jù)讀取

          讀文件是數(shù)據(jù)處理的第一步,pandas提供了read_xxx系列函數(shù),本次用到的是excel格式,因此使用read_excel即可,讀取成功后,用head查看數(shù)據(jù)樣例。

          data = pd.read_excel('data.xlsx')#讀取數(shù)據(jù)文件data.head()#查看樣例

          可以看到原始數(shù)據(jù)的列名為中文格式,為便于后續(xù)處理,我們統(tǒng)一改為英文,采用列名直接賦值的方式,如下面代碼。

          # 直接賦值修改列名data.columns=['id', 'order_id', 'city', 'cate', 'sub_cate', 'prod_name', 'sale_amt', 'amt']data.head()

          注意到prod_name包含的信息較多,逗號前是英文和中文名稱,逗號后是一些補充信息,我們使用split把它分隔開,因為分割出來是兩個字段,所以要寫成下面的形式,注意最后要加上str。

          data['prod_full_name'], data['remark'] = data['prod_name'].str.split(',').strdata.head(10)

          最后,我們可以篩選一些最終會用到的列,用于后面的處理。

          #列子集篩選data_new = data[['city', 'sub_cate', 'prod_full_name', 'amt']]data_new.head()

          2.分組聚合

          按照需求,需要計算每個城市每個子類別下產品的銷售總量,因此需要按照citysub_cate分組,并對amt求和。為計算占比,求得的和還需要和原始數(shù)據(jù)合在一塊作為新的一列。這里有兩種方式,可以先分組求和,再與原數(shù)據(jù)進行merge,也可以使用分組transform一步到位,在前面的文章Pandas tricks 之 transform的用法一文中有詳細的講解。這里采用第二種方式。計算的結果作為新的一列amt_sum添加到原數(shù)據(jù)上。

          #分組求和并用transform與原數(shù)據(jù)合并amt_sum = data_new.groupby(['city', 'sub_cate'])['amt'].transform('sum')data_new['amt_sum'] = amt_sumdata_new.head(10)

          為了驗證結果,我們取出city='杭州',sub_cate='用品'的所有樣本進行查看,這里用到了pandas多條件篩選數(shù)據(jù)操作。

          #多條件篩選,用&連接data_new[(data_new['sub_cate']=='用品') & (data_new['city'] == '杭州')]

          可以看到所有杭州,用品的銷售總量為18,和我們的計算結果一致。

          3.分組排序

          由于我們最終需要取排序Top3(或top50%)的產品,因此需要在各組內先按照銷售量降序排列,再計算百分比,最后求累計百分比。也可以先計算每個產品各自的占比,再排序之后求累計百分比。這里也采用第二種方式。

          #計算占比:data_new['pct'] = data_new['amt'] / data_new['amt_sum']data_new.head(10)

          各組內按銷售數(shù)量(或百分比)做降序。這里的排序有兩個層次的含義,第一種是組內實際順序不變,只給一個排序編號。代碼如下所示,method=first是保證序號是連續(xù)且唯一的。

          data_new['group_rank'] = data_new.groupby(['city', 'sub_cate'])['amt'].rank(method='first', ascending=False)data_new.head(10)

          同樣來看一下city='杭州',sub_cate='用品'的結果,如下圖所示,可以看到已經數(shù)量最多的編號為1,數(shù)量最少的編號為5,給出的序號并不是嚴格降序或升序的,說明數(shù)據(jù)的實際順序并沒有改變。

          第二種是排序之后,改變數(shù)據(jù)的實際順序。我們使用lambda函數(shù)實現(xiàn):對每個分組按照上一步生成的rank值,升序排列。

          data_sorted = data_new.groupby(['city', 'sub_cate']).apply(lambda x: x.sort_values('group_rank', ascending=True)).reset_index(drop=True)data_sorted.head(10)

          結果如上圖,這樣銷量占比最高的產品就會出現(xiàn)在每組的第一行。同樣看一下city='杭州',sub_cate='用品'的結果,發(fā)現(xiàn)amt,pct是降序的,group_rank是升序的。

          4.求累計占比

          前一步之所以要改變數(shù)據(jù)的順序,就是為了在這里算累計占比時,可以直接累加。我們需要對pct列求累計值,最終用來與目標值50%作比較。注意同樣是在每組內進行,需要用cumsum函數(shù)求累計和。

          #分組并用cumsum計算累計占比data_sorted['cum_pct'] = data_sorted.groupby(['city', 'sub_cate'])['pct'].cumsum()data_sorted.head(10)

          再來看一下city='杭州',sub_cate='用品'的結果。

          可以看到最后一列cum_pct已經按照pct列計算了累計百分比。其中累計到第二行的時候已經達到了61.1%,超過了50%,因此最終只需取前兩行即可。

          5.目標篩選

          經過了前面的數(shù)據(jù)準備,在這一步需要在每組內,篩選累計值達到50%的行,且最多三行。這里需要對每組內按行進行遍歷,用到了iterrows函數(shù),并判斷cum_pct50%,group_rank與3的關系。我們自定義一個函數(shù)來實現(xiàn)。

          def get_top_50_pct_rank(group_data, num=3, target=0.5):    res = -1    for index, grp in group_data.iterrows():        if grp['group_rank'] <= num and grp['cum_pct'] >= target:            res = grp['group_rank']            break        if grp['cum_pct'] < target and grp['group_rank'] == num:            res = num            break    return res

          調用該函數(shù)之后,對每個組能得到符合條件的目標group_rank值,如下面代碼和圖片所示:

          data_target_rank = data_sorted.groupby(['city', 'sub_cate']).apply(get_top_50_pct_rank).reset_index()data_target_rank.head()

          上圖第三列就是我們需要的目標group_rank值,注意先要把默認的名字改過來,并將此結果與原始數(shù)據(jù)做一個合并。在此基礎上,就可以將每組內不超過目標group_rank值的行篩選出來。

          #rename改名data_target_rank.rename(columns={0: 'target_get'}, inplace=True)#與原始數(shù)據(jù)mergemerge_data = pd.merge(data_sorted, data_target_rank,on=['city', 'sub_cate'], how='left')#篩選最終結果result_data = merge_data[merge_data['group_rank'] <= merge_data['target_get']]result_data.head()

          還是看一下city='杭州',sub_cate='用品'的最終結果:

          可以看出,該組內最初有5行數(shù)據(jù),篩選后剩下兩行,且銷售量占比超過50%,至此需求已基本實現(xiàn)。


          6.分組拼接

          在上一步篩選出了目標行,未達到最終目標,還需將每個分組內所有符合條件的產品名稱拼接起來,并用逗號隔開。這里采用分組對字符串求和的方式來實現(xiàn)。先在每個產品后面拼上一個逗號,然后“求和”,最后把末尾的逗號去掉。代碼如下:

          #給每一個產品名稱末尾拼接一個逗號result_data['prod_full_name'] = result_data['prod_full_name'].apply(lambda x: x + ',')result_data.head()

          #用求和的方式實現(xiàn)對產品名稱進行拼接result = result_data.groupby(['city', 'sub_cate'])['prod_full_name'].sum().reset_index()#去掉最末尾的逗號result['prod_full_name'] = result['prod_full_name'].apply(lambda x: x[:-1])

          result就是我們想要的目標dataframe。最終的city='杭州',sub_cate='用品'的結果如下。

          7.保存文件

          將上一步得到的result保存成Excel,即可得到文中開頭截圖的結果,使用to_excel方法,指定文件名,忽略索引即可。

          result.to_excel('result.xlsx', index=None)

          小結

          本文使用pandas,通過7個步驟實現(xiàn)了一個綜合案例:篩選出每個城市每個子類別中銷量占比top 50%的至多3個產品。涉及到的操作依次有:數(shù)據(jù)讀取,列名修改,字段分割,列子集篩選;分組求和(transform);分組排序(編號),分組排序;累計求和;按行迭代,數(shù)據(jù)拼接,條件篩選,分組拼接,apply/lambda函數(shù);保存文件等。有一些是核心操作,有一些只是輔助。可以用下圖來總結,帶有五角星的是核心操作,其余是輔助操作,葉子節(jié)點是用到的函數(shù)。

          瀏覽 48
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  西西4444WWW无码视频 | 久久久久久久极品内射 | 欧美精品一区二区三区免费久久久 | 一级片中文字幕 | 久久偷拍熟女91 |