Python大咖談 - Kenneth Reitz 與 Mike Driscoll
Python大咖談 - Brett Cannon(一)
Python大咖談 - Brett Cannon(二)
簡介
大家都知道 Excel 可以設(shè)定單元格格式,還支持單元格迷你圖,其實(shí) Pandas 也可以,本文參照 Chris Moffitt 的 Stylin’ with Pandas 一文,為大家簡單介紹一下 Pandas 如何實(shí)現(xiàn) DataFrame 的樣式設(shè)置,主要內(nèi)容如下:
設(shè)置 DataFrame 不同列的樣式,如千分號(hào)、小數(shù)位數(shù)、貨幣符號(hào)、日期格式,百分比等;
突出顯示 DataFrame 中某一列里符合某些條件的數(shù)據(jù),如,按不同顏色顯示某列中的最大值與最小值;
以不同漸變色展示每一行數(shù)據(jù)占總數(shù)據(jù)的比例大小,占比越大,顏色越深,占比越小,則顏色越淺;
實(shí)現(xiàn)類似 Excel 迷你條形圖的功能,根據(jù)數(shù)據(jù)大小,在單元格里顯示迷你條形圖;
利用 Sparklines 支持庫,配合 Pandas 繪制迷你走勢圖。需要先用
pip install sparklines
命令安裝 Sparklines 支持庫。
什么是樣式?為什么與使用樣式?
樣式的基本理念是用戶在調(diào)整數(shù)據(jù)顯示形式的同時(shí),不會(huì)影響數(shù)據(jù)本身的計(jì)算操作。
最直觀的樣式是貨幣符號(hào),如果只顯示一個(gè)數(shù)字,比如 25.06,讀者并不清楚這個(gè)數(shù)字代表的到底是美元、英鎊、日元還是人民幣,但 ¥25.06,大家就都知道這是人民幣了,由此可見,樣式可以讓數(shù)據(jù)提供更多信息。
百分比也是數(shù)據(jù)樣式的重要形式,0.12 就不如 12% 更直觀,用百分比說明數(shù)據(jù)更清晰,也更簡單。
Pandas 支持不同樣式,可以用更易理解的方式顯示數(shù)據(jù),但并未修改數(shù)據(jù)的類型,所以依然還可以用 Pandas 提供的各種數(shù)學(xué)、日期、字符串函數(shù)處理數(shù)據(jù)。
Pandas 樣式還包括內(nèi)容里提及的高級(jí)樣式,比如添加顏色與條形圖等可視化元素。本文只是簡要介紹 Pandas 樣式的基本功能,方便大家快速上手,提高數(shù)據(jù)分析報(bào)表的可讀性。
數(shù)據(jù)文件說明
數(shù)據(jù)文件為 2018年銷售匯總表.csv(點(diǎn)擊下載),本文件引用的是原文作者 Chris 虛構(gòu)的一家企業(yè) 2018 年的銷售數(shù)據(jù),但漢化了數(shù)據(jù)表的標(biāo)題,方便大家在代碼中識(shí)別數(shù)據(jù)列的信息;
文件格式從原文的
xlsx
改為csv
;文件共有 5 列,分別為賬號(hào)(字符串)、姓名(字符串)、單品(字符串)、數(shù)量(整數(shù))、單價(jià)(2 位小數(shù))、金額(2 位小數(shù))、日期(DateTime)
Jupyter Notebook 示例文件,點(diǎn)擊下載。
0.1 導(dǎo)入 Numpy 與 Pandas
import numpy as np
import pandas as pd
下面的代碼與原文不同,原文用的是 xlsx 文件,本文用的是 csv 文件,需要解析日期。
另外需要注意,數(shù)據(jù)文件與 ipynb 文件要在同一文件夾下。
df = pd.read_csv('2018年銷售匯總表.csv',parse_dates=['日期'])
0.2 df.head()
預(yù)覽數(shù)據(jù)
0.3 匯總數(shù)據(jù),根據(jù)客人姓名分組計(jì)算 2018 年每個(gè)客人的平均金額與消費(fèi)總額
df.groupby('姓名')['金額'].agg(['mean','sum'])
1.1 設(shè)置金額樣式:貨幣符號(hào)、千分號(hào)、2 位小數(shù)
可以看到平均值顯示的是 6 位小數(shù),沒有貨幣符號(hào),整數(shù)部分也沒有千分號(hào)。此時(shí),可以用 DataFrame 的 style.format
修飾。
代碼如下,匯總計(jì)算的代碼與上面相同,但多了 .style.format('${0:,.2f}')
,引號(hào)里的 $ 符號(hào)代表美元,冒號(hào)(:)后的逗號(hào)代表千分號(hào),.2f
代表 2 位小數(shù)。
(
df.groupby('姓名')['金額']
.agg(['mean', 'sum'])
.style.format('${0:,.2f}')
)
調(diào)整以后,數(shù)據(jù)顯示如下:
可以看到,用了 .style.format()
函數(shù)以后,DataFrame 中平均值(mean)列顯示的數(shù)據(jù)變成了帶美元符號(hào)標(biāo)記、整數(shù)部分帶千分號(hào)、小數(shù)僅保留兩位的樣式,這種樣式更便于理解金額這一概念。
如果只想保留整數(shù),可使用 .style.format('${0:,.0f}')
,把上面代碼里的 2 改為 0,即可。
(
df.groupby('姓名')['金額']
.agg(['mean', 'sum'])
.style.format('${0:,.0f}')
)
此時(shí),可以看到,貨幣數(shù)據(jù)已經(jīng)按四舍五入的原則保留了整數(shù)。
如需了解更多 Python 字符串格式化示例,請參照 Python String Format Cookbook 。
1.2 設(shè)定日期與百分比樣式
接下來用 groupby
函數(shù),按銷售日期計(jì)算每月銷售金額及其占年度銷售總額的比例。
monthly_sales = df.groupby([pd.Grouper(key='日期', freq='M')])['金額'].agg(['sum']).reset_index()
monthly_sales['月占比'] = monthly_sales['sum']/df['金額'].sum()
此處可以看到,日期顯示的是每個(gè)月的最后一天,比例一列則顯示為 6 位小數(shù),這種樣式顯然非常不直觀,但一列一列調(diào)整樣式也不是好方法,能不能一次性調(diào)整多列數(shù)據(jù)的樣式呢?答案自然是,能!用樣式字典就可以了。
format_dict = {'sum': '${0:,.0f}', '日期': '{:%Y-%m}', '月占比': '{:.2%}'}
monthly_sales.style.format(format_dict).hide_index()
上面的代碼,首先把 format_dict
定義為一個(gè)樣式字典,分別設(shè)置了匯總金額(sum)、日期、月占比三列的樣式。其中,匯總金額為帶美元符號(hào)、千分號(hào)、0 位小數(shù)的數(shù)字;日期為經(jīng)典的“年月”格式,月占比則為帶 2 位小數(shù)的百分比形式。
第二行代碼,使用 style.format()
調(diào)用了第一行代碼設(shè)定的樣式字典(format_dict
),并用 hide_index()
隱藏了索引,隱藏索引的功能在很多情況下都有用,大家可以試試。
這樣一來,DataFrame 的數(shù)據(jù)顯示就變得比較可耐了,是不是數(shù)據(jù)顯示得更清晰了,而且實(shí)現(xiàn)起來其實(shí)也很簡單。
2. 突出顯示最大值與最小值
Pandas 還支持用顏色突出顯示符合條件的數(shù)據(jù),類似 Excel 里的條件格式,本文主要演示一下如何突出顯示某列數(shù)據(jù)里的最大值(淺綠色)與最小值(紅色)。
(
monthly_sales
.style
.format(format_dict)
.hide_index()
.highlight_max(color='lightgreen')
.highlight_min(color='red')
)
這里的 color
參數(shù)除了可以用lightgreen
這樣的關(guān)鍵詞以外,還可以使用 '#cd4f39'
這樣的顏色代碼,更靈活。而且可以設(shè)置多個(gè)條件,比如可以同時(shí)設(shè)置 highlight_max
、highlight_min
。
3. 漸變色樣式
只改變數(shù)字的樣式,還不夠,我們還想要更多,還想用顏色的深淺漸變來表示某一列數(shù)據(jù)占比的多少,其實(shí)這也是 Excel 已經(jīng)提供了的功能,Pandas 也支持了。實(shí)現(xiàn)這一目標(biāo),需要使用 style
的 background_gradient
函數(shù)。
(
monthly_sales.style
.format(format_dict)
.background_gradient(subset=['sum'], cmap='BuGn')
)
上述代碼設(shè)定了顏色漸變針對(duì)的列,subset=['sum']
,色圖用的是 cmap 參數(shù),值為'BuGn',是一種綠色的漸變色圖,色圖的值請參閱 matplotlib 的文檔 ,還有更多色彩可選。
顯示效果如下,是不是覺得更直觀了?
4. 迷你條形圖樣式
除了漸變色,Pandas 還支持在 DataFrame 單元格里顯示迷你條形圖。
(
monthly_sales
.style
.format(format_dict)
.hide_index()
.bar(color='#FFA07A', vmin=100_000, subset=['sum'], align='zero')
.bar(color='lightblue', vmin=0, subset=['月占比'], align='zero')
.set_caption('2018年銷售一覽表')
)
這里使用的是 style
的 bar
函數(shù),分別需要設(shè)置幾個(gè)參數(shù),color
還是支持顏色編碼與關(guān)鍵詞,vmin
是基準(zhǔn)值,比如銷售額的基準(zhǔn)值是 10 萬,百分比的基準(zhǔn)值是 1,subset
是針對(duì)的列,align
則代表對(duì)齊方式。
此外,還可以用 set_caption
函數(shù)設(shè)置 DataFrame 的標(biāo)題。代碼執(zhí)行后,顯示效果如下。
5. Sparklines - 走勢圖
走勢圖這種樣式不是 Pandas 的內(nèi)置樣式,但依然很實(shí)用,也很酷,它是一個(gè)叫 sparklines 的支持庫提供的。詳情請參閱它的文檔 ,這個(gè)模塊可以為 Pandas 的 DataFrame 添加迷你走勢圖。
首先,導(dǎo)入 sparklines
;
import sparklines
接著,定義調(diào)用 sparklines
的函數(shù);
def sparkline_str(x):
bins=np.histogram(x)[0]
sl = ' '.join(sparklines(bins))
return sl
sparkline_str.__name__ = "走勢圖"
最后,在 groupby
函數(shù)里調(diào)用定義的 sparkline_str
函數(shù);
df.groupby('姓名')['數(shù)量', '金額'].agg(['mean', sparkline_str])
這種匯總功能可以很直觀的顯示數(shù)據(jù),更有趣的是這個(gè)走勢圖是由純文本組成的,又簡單,又實(shí)用,對(duì)不?
總結(jié)
Pandas 的樣式功能備受歡迎,尤其是分析師完成數(shù)據(jù)分析工作后,要給別人展示數(shù)據(jù)分析結(jié)果的時(shí)候,這個(gè)功能可以讓你的數(shù)據(jù)分析報(bào)告更直觀,更清晰。除了本文介紹的功能之外,其實(shí)還有更多樣式與函數(shù)功能供你選擇,本文只是引導(dǎo)您上手 Pandas 樣式的基礎(chǔ)入門,想要玩的更花俏,請自行研究 Pandas 官方的樣式文檔。
最后,感謝 Alexas_Fotos 提供的圖片,非常有創(chuàng)意。
Python大咖談 - Kenneth Reitz 與 Mike Driscoll
Python大咖談 - Brett Cannon(一)
Python大咖談 - Brett Cannon(二)
【呆鳥云】翻譯不易,四處求證、三天翻譯、兩天校對(duì),只求一秒點(diǎn)贊 _