如何使用辅助Y绘制带有分组索引的DataFrame

时间:2018-04-14 10:41:52

标签: python pandas dataframe plot yaxis

我有一个来自世界卫生组织的数据框,使用的是JSON,如此

import requests                 
import pandas as pd
import json
from pandas import read_html
from pandas.io.json import json_normalize   
import urllib2, json 
import html5lib

#Measles - Number of deaths of children < 5 by country & year
url = "http://apps.who.int/gho/athena/data/GHO/MORT_100.json?profile=simple&filter=COUNTRY:*;CHILDCAUSE:CH6"
response2 = urllib2.urlopen(url)
response_json2 = json.loads(response2.read())   
dfWHO2 = json_normalize(response_json2['fact'])
dfWHO2 = dfWHO2.loc[dfWHO2['dim.AGEGROUP']== '0-4 years']
WHOMeaslesChildhoodDeaths = dfWHO2.pivot('dim.COUNTRY','dim.YEAR','Value').astype(float)

#Measles First Dose Vaccination rate
url = "http://apps.who.int/gho/athena/data/GHO/WHS8_110.json?profile=simple&filter=COUNTRY:*"
response = urllib2.urlopen(url)
response_json = json.loads(response.read())
dfWHO1 = json_normalize(response_json['fact']).pivot('dim.COUNTRY','dim.YEAR','Value').astype(float)
WHOMeasles1stVaccRate = dfWHO1
WHOMeasles1stVaccRate = WHOMeasles1stVaccRate.loc[:,'2000':'2016']

#Combine Dataframes
WHOCombinedData = pd.concat([WHOMeasles1stVaccRate,WHOMeaslesChildhoodDeaths],axis=1,keys=['Rate','Deaths']).swaplevel(1,0,axis=1).sort_index(1)

#Transpose dataframes to get ready for Plotting
WHOData =  WHOCombinedData.transpose()

看起来像这样: WHOData Dataframe

    dim.COUNTRY Afghanistan Albania Algeria Andorra Angola
dim.YEAR                        
2000    Deaths  10580   2   1550    0   1536
        Rate    27      95  80      97  36
2001    Deaths  14120   0   1616    0   4643
        Rate    37      95  83      97  65
2002    Deaths  6891    0   1646    0   6061
        Rate    35      96  81      98  66
2003    Deaths  225     0   2567    0   2238
        Rate    39      93  84      96  52
2004    Deaths  367     0   38      0   36
        Rate    48      96  81      98  52
2005    Deaths  2042    0   32      0   432
        Rate    50      97  83      94  32

我想用2行绘制每个图中的每个列,一个用于死亡,一个用于速率。

因为比例是如此不同,我需要在辅助Y轴上绘制其中一个

第一个问题是我无法在第二个Y轴上获得RATE。

接下来的问题是我想一次绘制多个图表 - 每个列都有一个,但我不知道如何做到这一点。我确实试图一次绘制一个,而不是最好的方法,但它几乎可以工作,但是有近200个国家,所以做一个更聪明的方法是非常必要的。

这是我为单个图表尝试的内容:

ax = WHOData.loc[:,'Afghanistan':'Afghanistan'].unstack().plot(secondary_y='True' ,kind='line', stacked=True)
ax2 = ax.twinx()
plt.show()

这就是我得到的结果:

Dataframe Chart

我将非常感谢任何帮助

2 个答案:

答案 0 :(得分:1)

您可以迭代列,绘图并显示如下:

from matplotlib import pyplot as plt


for country in df.columns: # Iterate over countries
    df[[country]].unstack().plot(); # Unstack deaths and rates, plot
    plt.show(); # Switch to new plot

请注意使用pyplot.show

修改

要单独绘制死亡率和费率,您可以使用subplot

for country in df.columns: # Iterate over countries
    country_df = df[[country]].unstack().plot(); # Unstack deaths and rates
    subplot(2, 1, 1);
    plot(country_df[['Deaths']]);
    subplot(2, 1, 2)
    plot(country_df[['Rates']]);
    plt.show(); # Switch to new plot

答案 1 :(得分:1)

Ami的第一段代码回答了我的问题的第二部分,如何让每个国家在一个单独的地块上展示。不幸的是,他的第二段代码没有成功地给出如何在辅助y轴上绘制第二个系列。

在这里进行一些研究: Matplotlib - Plots with different scales

我终于弄清楚了。我要做的第一件事就是分开Deaths&amp;有效率。这是必需的,因为Dataframe是一个具有Rate&amp; amp;的多变量。每年死亡 - 每个国家多年

之后我需要让matplotlib与死亡分开提供YAXIS费率,因为在许多情况下规模差别很大

当然可以有更简洁的方式来编写代码,但这里有一组有效的代码:

for country in WHOData.columns: # Iterate over countries
    country_df = WHOData[[country]].unstack(); # Unstack deaths and rates
    deaths = country_df.iloc[:, country_df.columns.get_level_values(1)=='Deaths']
    rate = country_df.iloc[:, country_df.columns.get_level_values(1)=='Rate']
    fig, ax1 = plt.subplots()
    color = 'red'
    ax1.set_xlabel('Years')
    ax1.set_ylabel('Childhood (<4) Deaths by Measles', color=color)
    ax1.plot(deaths, color=color)
    ax1.tick_params(axis='y', labelcolor=color)

    ax2 = ax1.twinx()  # instantiate a second axes that shares the same x-axis

    color = 'blue'
    ax2.set_ylabel('Vaccination Rate 1st Dose', color=color)  # we already handled the x-label with ax1
    ax2.plot(rate, color=color)
    ax2.tick_params(axis='y', labelcolor=color)

    fig.tight_layout()  # otherwise the right y-label is slightly clipped
    plt.title(country)
    plt.show()

这就是它产生的:

enter image description here