小小明 凹凸數據
ide
小小明:「凹凸數據」專欄做者,Pandas數據處理專家,致力於幫助無數數據從業者解決數據處理難題。工具
凹凸們,你們好
先看一個小需求,實際上是很常見的分組聚合問題。
今天我將帶你們分別使用MySQL、Excel、Pandas、VBA和Python來實現這個需求。
這麼齊全的應該算是全網首發吧!固然也是爲了讓你們對分組聚合代碼層面的實現可以更加熟悉。
3d
SQL語句:調試
SELECT deal_date, SUM(IF(AREA= 'A區', 1, 0)) 'A區', SUM(IF(AREA= 'B區', 1, 0)) 'B區', SUM(IF(AREA= 'C區', 1, 0)) 'C區' FROM order_info GROUP BY deal_date ;
結果:
code
首先建立數據透視表:
而後將對應的字段拖動到正確的位置:
而後打開透視表選項取消這兩項勾選便可:
blog
讀取數據:ip
import pandas as pd df = pd.read_csv("data.csv", encoding="gb18030") df
結果:
使用數據透視表操做:ci
df.pivot_table(values="order_id", index="deal_date", columns="area", aggfunc="count", fill_value=0)
上述代碼至關於groupby操做:pandas
df.groupby(["deal_date", "area"])["order_id"].count().unstack(1, fill_value=0)
但我通常會這樣寫:it
df.groupby(["deal_date", "area"]).size().unstack(1, fill_value=0)
結果均爲:
通過近1小時的痛苦的嘗試,終於編寫出了下面這段VBA代碼,它模擬實現了分組計數的過程:
Option Explicit Function is_exists(name As String) Dim sht As Worksheet For Each sht In Worksheets If sht.name = name Then is_exists = True Exit Function End If Next is_exists = False End Function Sub 分組統計() Dim LastRow, LastCol As Long Dim Sh As Worksheet 'Sh指代當前活動頁 Set Sh = Sheets("data") '當前活動頁的最後一行 LastRow = Sh.Cells(Rows.Count, 1).End(xlUp).row '當前活動頁的最後一列 LastCol = Sh.Cells(1, Columns.Count).End(xlToLeft).Column '定義D爲字典 Dim D As Object Set D = CreateObject("Scripting.Dictionary") Dim row, i As Integer Dim key, value As String For i = 2 To LastRow key = Sh.Cells(i, 3).value value = Sh.Cells(i, 4).value '若是在字典裏 If Not D.exists(key) Then D.Add key, Array(0, 0, 0) End If row = D(key) If value = "A區" Then row(0) = row(0) + 1 ElseIf value = "B區" Then row(1) = row(1) + 1 ElseIf value = "C區" Then row(2) = row(2) + 1 End If D(key) = row Next '調試輸出字典存儲的內容 For Each key In D.keys() Debug.Print key & "," & Join(D(key), ",") Next Dim sht As Worksheet If is_exists("result") Then Sheets("result").Delete End If '在最後的位置增長一個sheet做爲結果表 Sheets.Add After:=Sheets(Sheets.Count) Set sht = Sheets(Sheets.Count) sht.name = "result" '屏幕刷新=false Application.ScreenUpdating = False '下面寫出數據到結果表中,首先寫出標題行 sht.Range("A1").Resize(1, 4) = Application.Transpose(Array("deal_date", "A區", "B區", "C區")) sht.Range("A2").Resize(D.Count, 1) = Application.Transpose(D.keys) i = 2 For Each row In D.items() sht.Cells(i, 2).Resize(1, 3) = row i = i + 1 Next Application.ScreenUpdating = True End Sub
運行前:
點擊按鈕運行後:
當即窗口和工做表都看到了正確的結果輸出,當即窗口看到重複2次的輸出是由於我連續運行了兩次。
實現代碼:
import csv from collections import namedtuple result = {} columns = ["A區", "B區", "C區"] areas_map = dict(zip(columns, range(len(columns)))) with open("data.csv", encoding="gb18030") as f: f_csv = csv.reader(f) headers = next(f_csv) resultSet = namedtuple("resultSet", headers) for r in f_csv: row = resultSet(*r) areas = result.setdefault(row.deal_date, [0, 0, 0]) areas[areas_map[row.area]] += 1 result
結果:
{'2019/1/1': [1, 1, 1], '2019/1/2': [1, 1, 1], '2019/1/3': [1, 0, 1]}
藉助Pandas轉換爲表結構方便查看:
pd.DataFrame.from_dict(result, 'index', columns=["A區", "B區", "C區"])
結果:
下面用Python模擬一下Pandas數據透視表實現分組統計的過程:
import csv from collections import namedtuple, Counter result = Counter() with open("data.csv", encoding="gb18030") as f: f_csv = csv.reader(f) headers = next(f_csv) resultSet = namedtuple("resultSet", headers) for r in f_csv: row = resultSet(*r) result[(row.deal_date, row.area)] += 1 result
結果:
Counter({('2019/1/1', 'A區'): 1, ('2019/1/1', 'B區'): 1, ('2019/1/1', 'C區'): 1, ('2019/1/2', 'A區'): 1, ('2019/1/2', 'B區'): 1, ('2019/1/2', 'C區'): 1, ('2019/1/3', 'A區'): 1, ('2019/1/3', 'C區'): 1})
第二步Pandas還需再對這個結果進行重塑才獲得最終所須要的結果,具體重塑的過程實際實現較爲複雜,但能夠藉助category的Series模擬實現一下:
indexs = result.keys() index = pd.Series(map(lambda x: x[0], indexs), dtype='category') columns = pd.Series(map(lambda x: x[1], indexs), dtype='category') values = result.values() data = np.zeros((len(index.cat.categories), len(columns.cat.categories))) for x, y, v in zip(index.cat.codes, columns.cat.codes, values): data[x, y] = v result = pd.DataFrame(data, index=index.cat.categories, columns=columns.cat.categories, dtype='int8') result
結果:
其實無論用什麼語言和工具,分組聚合統計的核心原理都是:
今天我給你們同時演示了MySQL、Excel、Pandas、VBA和Python實現分組聚合,經過對比,或許你們能本身總結出各項工具的優劣和適用場景。歡迎你在下方評論區留言,發表你的見解,給你們分享和互動。