這是一個關於 pandas 從基礎到進階的練習題系列,來源於 github 上的 guipsamora/pandas_exercises 。這個專案從基礎到進階,可以檢驗你有多麼瞭解 pandas。
我會挑選一些題目,並且
提供比原題庫更多的解決方法以及更詳盡的解析
。
計劃每天更新一期,希望各位小夥伴先自行思考,再檢視答案。如果對你有幫助,記得轉發推薦給你的好友!
上期文章:
pandas每天一題-題目8:去重計數的多種實現方式
我的 pandas 專欄,入門到高階應用全在裡面!
後臺回覆"資料",可以下載本題資料集
如下資料:
資料描述:
此資料是訂單明細表。一個訂單會包含很多明細項,表中每個樣本(每一行)表示一個明細項
order_id 列存在重複
quantity 是明細項數量
需求:
計算訂單平均收入?
說明:
假如有10筆訂單,總收入(quantity * item_price)是200,那麼訂單平均收入 = 200/10=20
雖然需求很簡單,但有些實現方式考驗你的 groupby 理解程度!
下面是答案了
方式1
初學者容易給出的錯誤答案是:
df = pd。read_csv(‘chipotle。tsv’,sep=‘\t’,converters={‘item_price’: lambda x: float(x[1:-1])})df。eval(‘quantity * item_price’)。mean()
這個結果實際是“訂單明細平均收入”
問題在於資料顆粒度不是一個訂單,而是一個訂單中的明細項。
因此第一種方式就是調整顆粒度:
( df。groupby(‘order_id’) 。apply( lambda g: g。eval(‘quantity * item_price’)。sum() ) 。mean())
21。394231188658654
行2:把細顆粒度轉粗顆粒度,彙總是最直接。按 order_id 分組即可
行3:由於收入需要計算,因此使用 apply 可以充分控制每一組彙總的細節
行4:引數 g 就是每個 order_id 的組,是一個表(DataFrame),這裡是計算總收入
行6:上一步的結果是一個表,顆粒度是每個訂單的收入。因此,直接求平均即可
使用 groupby+ apply 比較慢,我們可以把計算收入放在分組之前:
( df。eval(‘revenue=quantity * item_price’) 。groupby(‘order_id’) 。agg({‘revenue’:sum})[‘revenue’] 。mean())
行2:df。eval 可以直接表達新增列邏輯
行4:由於彙總邏輯更直接,不需要用apply ,可以直接用 agg。對 revenue 求和
但是 groupby + agg 出來的結果是一個表,如果直接求平均,會得到一個列(遍歷所有列求平均)。因此這裡需要取出 revenue 列
有沒有發現,收入只是一個臨時變數,但程式碼中卻多次出現(revenue)。可否省略?這引出方式2
方式2
pandas允許直接對列(Series)做分組:
( df。eval(‘quantity * item_price’) 。groupby(df。order_id) 。sum() 。mean())
行2:直接計算收入,此時得到的是列(Series)
行3:對列分組,但是列裡面沒有分組依據(order_id),我們可以直接把資料傳入。注意這裡不是列名(字串),而是一列資料
行4:這裡的 sum 是 groupby 後的操作,表達的是每一組的統計方式,我們需要求總訂單收入
行5:上一步得到每個訂單的收入,仍然是列(Series),直接求平均,就能得到一個數值
點評:
這種方式最直觀,無須中間變數
推薦閱讀:
pandas每天一題-題目5:統計空值數量也有多種實現方式
pandas每天一題-題目1、2、3
懂Excel就能輕鬆入門Python資料分析包pandas(五):重複值處理
Python進階系列:細講Python推導式