pivot_table 之使用
Table of contents
背景
- 這個範例檢討售案與權利人之間的關聯性。
- 「權利人」:此處假設權利人是個投票的群體,否同意接受方案的條件從而接受方案,他們的決定將會是售案順利售出的關鍵。
- 「貢獻度」:雖然無從得知每個權利人對售案的態度,由於售案最後可能採行多數決、也可能使用共識決,不論如何,此處定義售案成功可以平均歸功於參與售案評估的每一個權利人,如此可以計算每個權利人對群體(公司或團隊)年度成交總額的貢獻比例程度。
- 以此討論年度間的差異,找出重要關鍵權利人、或者權利人對群體的態度轉變趨勢,提供決策參考。
- 本範例為使用
pivot_tables
、sort_values`等pandas中的重要模組。
程式功能概述
本程式主要負責讀取不同年度的 crawler.csv
檔案,分析各年度的權利人姓名(name)與金額(budg)之間的關係,並計算不同姓名的影響程度。
最終輸出兩個 CSV 檔案
dfnps.csv
:篩選出 2024 年金額比例小於 2022-2023 平均值的姓名。dfnpsGTavg.csv
:篩選出 2024 年金額比例大於或等於 2022-2023 平均值的姓名。
程式碼說明
** 程式輸入**
- 主要輸入:
2022_crawler.csv
2023_crawler.csv
2024_crawler.csv
2025_crawler.csv
- 輸入格式:CSV 檔案,包含以下欄位:
姓名
:含有姓名的字串資料。範例如下{'張○○': ['經歷1:', '服務機關(構)名稱:○○大學(○○工程系),職稱:助...]}
金額
:專案的金額。是否售出
:布林值,表示是否售出。主辦部
:該售案的主辦單位。
** 主要邏輯與運算**
(1) 讀取 CSV 檔案
使用 pandas.read_csv
讀取 CSV 檔案,並存入 DataFrame
。
fname='/Users/user1/Downloads/2024_crawler.csv'
df=read_csv(fname, encoding='utf8')
(2) 從 姓名
欄位解析出姓名
s2names(s)
函數負責解析姓名,透過find("':")
來定位姓名的名稱。- 迴圈解析字串內容,並將姓名存入
names
陣列。
def s2names(s):
names = []
i = 0
while i < len(s):
end = s.find(":'", i)
if end == -1:
break
start = s.find("'", end - 4)
name = s[start+1:end]
names.append(name)
i = end + 1
return names
** 建立年度資料處理迴圈**
讀取 2022-2025
四年的 CSV 檔案,並針對每一筆資料:
- 使用
s2names()
解析姓名
欄位的姓名。 - 計算權利人對該售案金額的影響程度(平均分配給該售案權利人的所有姓名)。
- 將數據存入
years
,names
,budgs
,depgr
等陣列。
for fname in fnames[:-1]:
yr = fname[23:27]
df = read_csv(fname, encoding='utf8')
for i in range(len(df)):
s = df.loc[i, '姓名']
if type(s) != str: continue
name_list = s2names(s)
budg = df.loc[i, '金額'] / len(name_list)
if not df.loc[i, '是否售出']: budg *= -1
for name in name_list:
names.append(name)
budgs.append(budg)
depgr.append(df.loc[i, '主辦部'])
years.append(yr)
(4) 計算每位姓名的影響比例
建立 pivot_table()
來彙總 budg
數值,並計算該姓名佔該年度總金額的比例。
pv = pivot_table(dff, index=['year', 'name'], values=['budg'], aggfunc=sum).reset_index()
yr_sum = {i: dff.loc[dff.year.astype(int) == i, 'budg'].sum() for i in range(2022, 2026)}
pv.year = [int(i) for i in pv.year]
pv['budg_rate'] = [i / yr_sum[j] for i, j in zip(pv.budg, pv.year)]
(5) 按 budg_rate
排序,姓名
pvm = pivot_table(pv, index=['name'], values=['budg_rate'], aggfunc=np.mean).reset_index()
pvms = pvm.sort_values(by='budg_rate', ascending=False).reset_index(drop=True)
(6) 篩選特定條件的姓名並輸出 CSV
dfnps.csv
: 篩選出2024
影響力 低於2022-2023
平均的姓名。dfnpsGTavg.csv
: 篩選出2024
影響力 大於或等於2022-2023
平均的姓名。
idx = np.where(df_name_yr.y2022 * df_name_yr.y2023 * df_name_yr.y2024 > 0)
names, percent = [], []
for i in idx[0]:
avg = (df_name_yr.loc[i, 'y2022'] + df_name_yr.loc[i, 'y2023']) / 2.
if df_name_yr.loc[i, 'y2024'] < avg:
name = df_name_yr.loc[i, 'name']
names.append(name)
percent.append(round(100 * list(pvms.loc[pvms.name == name, 'budg_rate'])[0], 3))
dfnp = DataFrame({'name': names, 'percent': percent})
dfnps = dfnp.sort_values(by='percent', ascending=False).reset_index(drop=True)
dfnps.to_csv('dfnps.csv', index=False)
4. 程式輸出
dfnps.csv
:2024 年影響力下降的姓名。dfnpsGTavg.csv
:2024 年影響力上升或持平的姓名。
5. 注意事項
- 資料清理:確保
姓名
欄位為str
類型,否則s2names()
可能會出錯。 - 金額計算:若姓名人數較多,
budg
會被平均分配,需確認該計算方式是否符合業務邏輯。 - 年度範圍:目前程式支援
2022-2025
,如需擴展,請修改fnames
及yr_sum
相關計算。 - CSV 輸出格式:最終的
dfnps.csv
及dfnpsGTavg.csv
會按照percent
由高到低排序。