2016-11-24 63 views
0

我的csv數據看起來像下面提供的數據。我想用pandas/python創建一個堆棧條圖,其中每個條代表兩種顏色的男性和女性部分,在條的頂部顯示男性和女性服用藥物的總數(在我的情況下)。例如,對於20歲的秋季,共有7人,其中6人是男性,1人是女性,因此酒吧的情節應該在酒吧的頂部有7個,這個6:1的部分顯示在酒吧中兩種顏色。我設法根據他們的年齡計數將他們分組並繪製出來,但我想以兩種不同顏色的性別來展示酒吧。任何幫助將不勝感激 。謝謝。按熊貓羣組計算的堆積條形圖

Drug_ID,Age,Gender 
FF90E5F780133BBCAEE9BA0E4654C5CA,15,F 
2AB2529352E6A1D0BA91E167C5191231,17,M 
6E4B2C80EA83C5B51675BC077A182E06,19,M 
8AEB19A68DE4C301154973E0C87C774D,19,M 
FA533E7DD1FCAB83822D4A2FC514AEE7,20,F 
208F39485A8FBA7214CA004B53CC29B7,20,M 
3172B95E8A5732D2EDB089A354787612,20,M 
38FBAE52AAB04E56AB3A35C4AFBF3813,20,M 
62D8A33130574C984EAF3A2E80C243A6,20,M 
646AF35E192885FE1336649BA3735FC4,20,M 
778D2B1354F30ED3D3BDD7B9437CF670,20,M 
891312933FE5FB25703B3E958EF943E3,21,F 
5CC63DFC5EF399F65CB9BC583A770DFB,21,M 
97C9ED5750EC6FF618A059085F0BF4A6,21,M 
C6F03C5E3CC37249E0308A09292F5A58,21,M 
0713C427BDC3A90F291AF49599987F38,23,F 
518EBD35FCDAB7C744334F993D8CEB28,23,F 
A3FC185C4531AFF1E8B7B9F5985028CB,23,F 
1837406921314CB182FB0C7BC5565204,23,M 
CA0E6274BD39E8DE5C823F4E6F234252,23,M 
E2F64030BB011C11541EDC192BAED09A,23,M 
EF8F3D028C5759858AB7574864833015,23,M 
5DCD427F26E05CC1C3F565BB05EAE10B,24,F 
8646ED503722C3C6C6B44208EF1A5202,24,F 
F9F45112C472282778E1F437F54B0B70,24,F 
0CF4F20B89303CB4C03CF3BD3B27CAF0,24,M 
63727039DFF77A46995DA8EDBC4E3497,24,M 

import matplotlib.pyplot as plt 
import pandas as pd 
import numpy as np 

data = pd.read_csv('/home/MedResearch/Desktop/drug_ids_age_gender.csv') 
data.values 

df = pd.DataFrame(data) 
df2 = pd.merge(df1,df, left_index = True, right_index = True) 
temp1 = df2.groupby('Age').Age.count() 

df3 = pd.merge(df1,df, left_index = True, right_index = True) 
temp2 = df3.groupby('Gender').Age.count() 

ax = temp1.plot(kind='bar',stacked = False, colormap = 'Paired') 
for p in ax.patches: 
    ax.annotate(np.round(p.get_height(),decimals=0), (p.get_x()+p.get_width()/2., p.get_height()), ha='center', va='center', xytext=(2, 10), textcoords='offset points') 
plt.ylabel('Numbers Of Patients Taking the drug') 
plt.title('Age Distribution Of Patients Based Upon drug Intake') 
plt.show() 

得到了這樣的結果:

enter image description here

回答

3

這個問題經常回來,所以我決定寫一步步解釋。請注意,我不是pandas古茹,所以有些東西可能會被優化。

我開始產生越來越,我會用我的x軸時代的列表:

cvsdata = '''Drug_ID,Age,Gender 
FF90E5F780133BBCAEE9BA0E4654C5CA,15,F 
2AB2529352E6A1D0BA91E167C5191231,17,M 
6E4B2C80EA83C5B51675BC077A182E06,19,M 
8AEB19A68DE4C301154973E0C87C774D,19,M 
FA533E7DD1FCAB83822D4A2FC514AEE7,20,F 
208F39485A8FBA7214CA004B53CC29B7,20,M 
3172B95E8A5732D2EDB089A354787612,20,M 
38FBAE52AAB04E56AB3A35C4AFBF3813,20,M 
62D8A33130574C984EAF3A2E80C243A6,20,M 
646AF35E192885FE1336649BA3735FC4,20,M 
778D2B1354F30ED3D3BDD7B9437CF670,20,M 
891312933FE5FB25703B3E958EF943E3,21,F 
5CC63DFC5EF399F65CB9BC583A770DFB,21,M 
97C9ED5750EC6FF618A059085F0BF4A6,21,M 
C6F03C5E3CC37249E0308A09292F5A58,21,M 
0713C427BDC3A90F291AF49599987F38,23,F 
518EBD35FCDAB7C744334F993D8CEB28,23,F 
A3FC185C4531AFF1E8B7B9F5985028CB,23,F 
1837406921314CB182FB0C7BC5565204,23,M 
CA0E6274BD39E8DE5C823F4E6F234252,23,M 
E2F64030BB011C11541EDC192BAED09A,23,M 
EF8F3D028C5759858AB7574864833015,23,M 
5DCD427F26E05CC1C3F565BB05EAE10B,24,F 
8646ED503722C3C6C6B44208EF1A5202,24,F 
F9F45112C472282778E1F437F54B0B70,24,F 
0CF4F20B89303CB4C03CF3BD3B27CAF0,24,M 
63727039DFF77A46995DA8EDBC4E3497,24,M''' 

df = pd.read_csv(StringIO.StringIO(cvsdata)) 
ages = df.Age.unique() 

array([15, 17, 19, 20, 21, 23, 24]) 

然後,我產生一個分組數據幀,每個M和F的每個年齡的計數:

counts = df.groupby(['Age','Gender']).count() 
print counts 

      Drug_ID 
Age Gender   
15 F    1 
17 M    1 
19 M    2 
20 F    1 
    M    6 
21 F    1 
    M    3 
23 F    3 
    M    4 
24 F    3 
    M    2 

利用這一點,我可以很容易地計算出個人每個年齡組的總人數:

totals = counts.sum(level=0) 
print totals 

    Drug_ID 
Age   
15   1 
17   1 
19   2 
20   7 
21   4 
23   7 
24   5 

爲了準備繪圖,我將轉換我的counts數據框以按列分隔各個性別,而不是索引。在這裏,我還放棄'Drug_ID'列名稱,因爲unstack()操作會創建MultiIndex,並且操作沒有該MultiIndex的數據框會更容易。

counts = counts.unstack(level=1) 
counts.columns = counts.columns.droplevel(level=0) 
print counts 

Gender F M 
Age    
15  1.0 NaN 
17  NaN 1.0 
19  NaN 2.0 
20  1.0 6.0 
21  1.0 3.0 
23  3.0 4.0 
24  3.0 2.0 

看起來不錯。我只是做最後的改進和更換NaN 0.

counts = counts.fillna(0) 
print counts 

Gender F M 
Age    
15  1.0 0.0 
17  0.0 1.0 
19  0.0 2.0 
20  1.0 6.0 
21  1.0 3.0 
23  3.0 4.0 
24  3.0 2.0 

有了這個數據幀,實在是小巫見大巫繪製堆疊條形:

plt.bar(ages, counts['M'], bottom=None, color='blue', label='M') 
plt.bar(ages, counts['F'], bottom=counts['M'], color='pink', label='F') 
plt.legend() 
plt.xlabel('Ages') 
plt.ylabel('Count') 

要繪製之上的總計數酒吧,我們將使用annotate()函數。我們無法一次完成,取而代之的是我們將循環訪問agestotals(爲了簡單起見,我將valuesflatten()分別列出,因爲它們格式不正確,不太清楚爲什麼)

for age,tot in zip(ages,totals.values.flatten()): 
    plt.annotate('N={:d}'.format(tot), xy=(age+0.4, tot), xytext=(0,5), textcoords='offset points', ha='center', va='bottom') 

的註解座標是(age+0.4, tot)因爲試條xx+widthwidth=0.8默認情況下,因此x+0.4是酒吧的中心,而tot當然是棒的整個高度。爲了稍微偏移文本,我在y方向上將文本偏移了幾(5)個點。根據你的喜好調整。

檢出the documentation for bar()來調整條形圖的參數。 退房the documentation for annotate()自定義您的註釋

enter image description here

+0

謝謝Diziet進行徹底的解釋。 –

+0

不客氣,如果我的回答有幫助並回答您的問題,請考慮通過點擊答案旁邊的複選標記來接受它。 –

+0

對不起。是的,我檢查標記 –