01 帶餅圖的散點(diǎn)圖
有這樣一個(gè)例子:假設(shè)有五個(gè)人查描,每個(gè)人的月均收入水平為a=[1,3,2,4,3]扣蜻,消費(fèi)水平b=[2,1,3,3,5]走孽,數(shù)據(jù)單位均有千元钝的。同時(shí)五個(gè)人消費(fèi)水平中翁垂,按照每月衣食住行的消費(fèi)比例為:
s1=[0.1,0.2,0.3,0.4]
s2=[0.35,0.35,0.2,0.1]
s3=[0.2,0.25,0.25,0.3]
s4=[0.5,0.1,0.15,0.25]
s5=[0.0,0.25,0.4,0.35]
依據(jù)上述數(shù)據(jù)(數(shù)據(jù)純屬虛構(gòu)),我可以將這些數(shù)據(jù)畫(huà)在一個(gè)圖形里硝桩,如圖:(其中沿猜,藍(lán)色:衣;黃色:食碗脊;紅色:滋浼纭;綠色:行)
這個(gè)圖形就是帶餅圖的散點(diǎn)圖衙伶,從圖中不僅可以看出五個(gè)人的消費(fèi)與收入的關(guān)系趨勢(shì)祈坠,也可以看出每個(gè)人的衣食住行消費(fèi)比例不同。
是不是很有趣的一個(gè)圖形矢劲?它是怎么做出來(lái)的赦拘?
02 matplotlib中marker參數(shù)的一個(gè)隱藏功能
上圖是用python中matplotlib包繪制的,而繪制成帶餅圖的散點(diǎn)圖則是用了里邊關(guān)鍵的marker參數(shù)卧须,所以在介紹如何繪制此圖之前另绩,先說(shuō)說(shuō)marker參數(shù)的一個(gè)隱藏功能儒陨。
一般的我們繪制散點(diǎn)圖基本的命令為:
import matplotlib.pyplot as plt
plt.scatter(x, y, s=20, c=None, marker='o')
其中,s是點(diǎn)的大小笋籽,c是顏色蹦漠,marker就是指定點(diǎn)標(biāo)記的形狀,在這里用的就是小圓點(diǎn)o车海;我們還可以用“*”笛园、“x”、“Δ”等等侍芝,甚至還有數(shù)字研铆、字母所代表的形狀。
03 單個(gè)帶餅圖的散點(diǎn)圖繪制過(guò)程
但是萝挤,完全繪制成上述那個(gè)圖形也并非那么容易御毅,下面我們從一個(gè)帶餅圖的散點(diǎn)繪制講起。
比如上面的a=1平斩,b=2那個(gè)點(diǎn)的消費(fèi)比例為:s1=[0.1,0.2,0.3,0.4]亚享,代碼如下:
x = [0] + np.cos(np.linspace(0, 2 * np.pi * 0.1, 5)).tolist()#[0]表示x的初始值
y = [0] + np.sin(np.linspace(0, 2 * np.pi * 0.1, 5)).tolist() #用tolist()形成數(shù)列
xy1 = list(zip(x, y))
x = [0] + np.cos(np.linspace(2 * np.pi * 0.1, 2 * np.pi * 0.3, 5)).tolist()
y = [0] + np.sin(np.linspace(2 * np.pi * 0.1, 2 * np.pi * 0.3, 5)).tolist()
xy2 = list(zip(x, y))
x = [0] + np.cos(np.linspace(2 * np.pi * 0.3, 2 * np.pi* 0.6, 5)).tolist()
y = [0] + np.sin(np.linspace(2 * np.pi * 0.3, 2 * np.pi* 0.6, 5)).tolist()
xy3 = list(zip(x, y))
x = [0] + np.cos(np.linspace(2 * np.pi * 0.6, 2 * np.pi*1, 5)).tolist()
y = [0] + np.sin(np.linspace(2 * np.pi * 0.6, 2 * np.pi*1, 5)).tolist()
xy4 = list(zip(x, y))
fig, ax = plt.subplots()
ax.scatter(a[0], b[0], marker=(xy1),
s=500,facecolor='blue')
ax.scatter(a[0], b[0], marker=(xy2),
s=500,facecolor='y')
ax.scatter(a[0], b[0], marker=(xy3),
s=500,facecolor='red')
ax.scatter(a[0], b[0], marker=(xy4),
s=500,facecolor='green') #為了餅圖看得清,散點(diǎn)的size要大一些
plt.show()
得到結(jié)果就是:首先講講x绘面、y變量的生成欺税,其原理是先根據(jù)每個(gè)占比數(shù)值所形成的角度(乘以2π,如2 * np.pi * 0.1)揭璃,然后再用np.linspace函數(shù)五等分形成6個(gè)角度值晚凿,每個(gè)值賦予cos、sin函數(shù)瘦馍,這是因?yàn)閏os2θ+sin2θ=1歼秽,所有經(jīng)過(guò)cos、sin函數(shù)的值會(huì)自動(dòng)形成一個(gè)圓形情组。
值得注意的是燥筷,因?yàn)樗膫€(gè)占比要圍成一個(gè)圓形箩祥,所以除了第一個(gè)占比外,后邊的都要用累計(jì)占比肆氓,如第二個(gè)0.2的占比np.linspace(2 * np.pi * 0.1, 2 * np.pi * 0.3, 5)袍祖,第三個(gè)0.3的就是0.3-0.6之間,第四個(gè)是0.6-1之間谢揪。
如果還沒(méi)明白那就單獨(dú)把一個(gè)x蕉陋、y生成的變量,單獨(dú)作圖可以看一下:
x = [0] + np.cos(np.linspace(0, 2 * np.pi * 0.1, 5)).tolist()
y = [0] + np.sin(np.linspace(0, 2 * np.pi * 0.1, 5)).tolist()
plt.plot(x,y,c='b')
plt.show()
可以看出拨扶,第一個(gè)占比x凳鬓、y的軌跡就是一個(gè)弧形,然后再用初始值(0患民,0)牽引著缩举,這樣再對(duì)這個(gè)軌跡進(jìn)行填充時(shí),就會(huì)形成一個(gè)扇形酒奶,如下:
plt.scatter(a[0], b[0], marker=(xy1),
s=500,facecolor='blue')
plt.show()
這樣一個(gè)x蚁孔、y所形成的marker=(xy1)標(biāo)記,再用facecolor='blue'填充就會(huì)形成一個(gè)扇形散點(diǎn)標(biāo)記惋嚎。最后用fig, ax = plt.subplots()把xy2、xy3站刑、xy4所有子圖都放上去另伍,就形成一個(gè)圓形,然后用不同顏色填充绞旅,就形成一個(gè)餅圖摆尝,每個(gè)餅圖的角度大小由其占比比例決定。
04 所有點(diǎn)的餅圖-散點(diǎn)圖
上邊是一個(gè)點(diǎn)的餅圖-散點(diǎn)圖因悲,若是將a=[1,3,2,4,3]堕汞,b=[2,1,3,3,5],以及b的所有個(gè)體衣食住行的消費(fèi)比例全放進(jìn)去晃琳,那就需要用到while讯检、for循環(huán)條件,代碼如下:
#5個(gè)消費(fèi)水平下衣食住行的占比
s1=[0.1,0.2,0.3,0.4]
s2=[0.35,0.35,0.2,0.1]
s3=[0.2,0.25,0.25,0.3]
s4=[0.5,0.1,0.15,0.25]
s5=[0.0,0.25,0.4,0.35]
#計(jì)算累計(jì)占比
ss1=[s1[0],sum(s1[0:2]),sum(s1[0:3]),sum(s1[0:4])]
ss2=[s2[0],sum(s2[0:2]),sum(s2[0:3]),sum(s2[0:4])]
ss3=[s3[0],sum(s3[0:2]),sum(s3[0:3]),sum(s3[0:4])]
ss4=[s4[0],sum(s4[0:2]),sum(s4[0:3]),sum(s4[0:4])]
ss5=[s5[0],sum(s5[0:2]),sum(s5[0:3]),sum(s5[0:4])]
s=[ss1,ss2,ss3,ss4,ss5]
a=[1,3,2,4,3] #收入水平(千元)
b=[2,1,3,3,5] #消費(fèi)水平(千元)
fig, ax = plt.subplots(figsize=(10,6))
i=0
while i<len(b):
x = [0] + np.cos(np.linspace(0, 2 * np.pi * s[i][0], 15)).tolist()
y = [0] + np.sin(np.linspace(0, 2 * np.pi * s[i][0], 15)).tolist()
xy1 = list(zip(x, y))
x = [0] + np.cos(np.linspace(2 * np.pi * s[i][0], 2 * np.pi * s[i][1], 15)).tolist()
y = [0] + np.sin(np.linspace(2 * np.pi * s[i][0], 2 * np.pi * s[i][1], 15)).tolist()
xy2 = list(zip(x, y))
x = [0] + np.cos(np.linspace(2 * np.pi * s[i][1],
2 * np.pi* s[i][2], 15)).tolist()
y = [0] + np.sin(np.linspace(2 * np.pi * s[i][1],
2 * np.pi* s[i][2], 15)).tolist()
xy3 = list(zip(x, y))
x = [0] + np.cos(np.linspace(2 * np.pi * s[i][2],
2 * np.pi*1, 15)).tolist()
y = [0] + np.sin(np.linspace(2 * np.pi * s[i][2],
2 * np.pi*1, 15)).tolist()
xy4 = list(zip(x, y))
xy=[xy1,xy2,xy3,xy4]
c=['b','y','r','g']
for j in range(4):
ax.scatter(a[i], b[i], marker=(xy[j]),
s=800,facecolor=c[j])
i=i+1
plt.show()
最終得到本文前邊那個(gè)圖形卫旱。
另外還需說(shuō)明一下人灼,這個(gè)圖形只適用于小樣本數(shù)據(jù),也就是圖形三點(diǎn)的個(gè)數(shù)不能太多顾翼,每個(gè)點(diǎn)中比例數(shù)量也不能太多投放,否則影響展示效果。
寫(xiě)作不易适贸,特別是技術(shù)類的寫(xiě)作灸芳,請(qǐng)大家多多支持涝桅,關(guān)注、點(diǎn)贊烙样、轉(zhuǎn)發(fā)等等苹支,也歡迎大家關(guān)注知乎爬蟲(chóng)與數(shù)據(jù)分析專欄:https://zhuanlan.zhihu.com/zjying2000。