使用 pivot-table 计算百分比和绘图

Calculation percentage and plot using pivot-table

我需要在 pandas 中绘制带有枢轴 table 的百分比图形,您有什么想法吗?我如何计算百分比?感谢您的指导!

这是我的代码:

df.pivot_table(index='obito', values=['asma', 'cardiopatia','diabetes','doenca_renal','obesidade']).T.plot(kind ='bar' , stacked = True)

我拥有的这部分数据框:

{'nome_munic': {66: 'Ferraz de Vasconcelos',
  97: 'São Paulo',
  100: 'São José dos Campos',
  207: 'Mauá',
  249: 'Cajamar',
  258: 'Votuporanga',
  285: 'Ferraz de Vasconcelos',
  290: 'São Paulo',
  345: 'São Pedro',
  378: 'São Paulo'},
 'codigo_ibge': {66: 3515707,
  97: 3550308,
  100: 3549904,
  207: 3529401,
  249: 3509205,
  258: 3557105,
  285: 3515707,
  290: 3550308,
  345: 3550407,
  378: 3550308},
 'idade': {66: 86,
  97: 62,
  100: 58,
  207: 54,
  249: 62,
  258: 37,
  285: 54,
  290: 71,
  345: 79,
  378: 61},
 'sexo': {66: 0,
  97: 0,
  100: 0,
  207: 1,
  249: 0,
  258: 1,
  285: 0,
  290: 0,
  345: 0,
  378: 0},
 'obito': {66: 1,
  97: 0,
  100: 0,
  207: 1,
  249: 1,
  258: 1,
  285: 0,
  290: 1,
  345: 1,
  378: 0},
 'asma': {66: 0,
  97: 0,
  100: 0,
  207: 1,
  249: 0,
  258: 0,
  285: 0,
  290: 0,
  345: 0,
  378: 0},
 'cardiopatia': {66: 1,
  97: 0,
  100: 1,
  207: 1,
  249: 1,
  258: 0,
  285: 1,
  290: 1,
  345: 0,
  378: 0},
 'diabetes': {66: 1,
  97: 1,
  100: 0,
  207: 0,
  249: 1,
  258: 1,
  285: 0,
  290: 0,
  345: 1,
  378: 0},
 'doenca_hematologica': {66: 0,
  97: 0,
  100: 0,
  207: 0,
  249: 0,
  258: 0,
  285: 0,
  290: 0,
  345: 0,
  378: 0},
 'doenca_hepatica': {66: 0,
  97: 0,
  100: 0,
  207: 0,
  249: 0,
  258: 0,
  285: 0,
  290: 0,
  345: 0,
  378: 0},
 'doenca_neurologica': {66: 0,
  97: 0,
  100: 0,
  207: 0,
  249: 0,
  258: 0,
  285: 0,
  290: 1,
  345: 0,
  378: 0},
 'doenca_renal': {66: 0,
  97: 0,
  100: 0,
  207: 0,
  249: 0,
  258: 0,
  285: 0,
  290: 0,
  345: 0,
  378: 0},
 'imunodepressao': {66: 0,
  97: 0,
  100: 1,
  207: 0,
  249: 0,
  258: 0,
  285: 0,
  290: 0,
  345: 0,
  378: 0},
 'obesidade': {66: 0,
  97: 0,
  100: 0,
  207: 0,
  249: 1,
  258: 1,
  285: 0,
  290: 0,
  345: 0,
  378: 0},
 'outros_fatores_de_risco': {66: 0,
  97: 0,
  100: 1,
  207: 0,
  249: 0,
  258: 0,
  285: 0,
  290: 0,
  345: 0,
  378: 1},
 'pneumopatia': {66: 0,
  97: 1,
  100: 0,
  207: 0,
  249: 0,
  258: 0,
  285: 0,
  290: 0,
  345: 0,
  378: 0},
 'puerpera': {66: 0,
  97: 0,
  100: 0,
  207: 0,
  249: 0,
  258: 0,
  285: 0,
  290: 0,
  345: 0,
  378: 0},
 'sindrome_de_down': {66: 0,
  97: 0,
  100: 0,
  207: 0,
  249: 0,
  258: 0,
  285: 0,
  290: 0,
  345: 0,
  378: 0}} 

感谢您的支持。

默认的 aggfunc 是 np.mean 但是它不计算每列的平均值或类似的东西,它计算单元格的平均值。简而言之,对于每种情况,它都是 1 的数量除以 1 的数量 + 0 的数量。这有时是有道理的,但对您的数据而言并非如此。

>>> df[['asma', 'cardiopatia','diabetes','doenca_renal','obesidade', 'obito']]
     asma  cardiopatia  diabetes  doenca_renal  obesidade  obito
66      0            1         1             0          0      1
97      0            0         1             0          0      0
100     0            1         0             0          0      0
207     1            1         0             0          0      1
249     0            1         1             0          1      1
258     0            0         1             0          1      1
285     0            1         0             0          0      0
290     0            1         0             0          0      1
345     0            0         1             0          0      1
378     0            0         0             0          0      0
>>> df.pivot_table(index='obito', values=['asma', 'cardiopatia','diabetes','doenca_renal','obesidade'])
           asma  cardiopatia  diabetes  doenca_renal  obesidade
obito                                                          
0      0.000000     0.500000  0.250000             0   0.000000
1      0.166667     0.666667  0.666667             0   0.333333

相反,您可能想计算每个单元格的患者总数,然后除以列总数:

>>> counts = df.pivot_table(index='obito', values=['asma', 'cardiopatia','diabetes','doenca_renal','obesidade'], aggfunc=np.sum)
>>> counts / counts.sum()
       asma  cardiopatia  diabetes  doenca_renal  obesidade
obito                                                      
0       0.0     0.333333       0.2           NaN        0.0
1       1.0     0.666667       0.8           NaN        1.0

请注意现在每列的总和为 1。doenca_renalNaN,因为样本中根本没有患者,因此未定义百分比。如果您只想绘制具有 obito=1 的百分比,那么您可以这样做:

>>> from matplotlib import ticker
>>> ax = (counts / counts.sum()).loc[1].plot.bar(rot=0)
>>> ax.yaxis.set_major_formatter(ticker.PercentFormatter(xmax=1))

如果要在栏上注释百分比,请参阅 this other question