如何在matplotlib中制作带注释的分组堆积条形图?

时间:2020-09-01 23:48:37

标签: python matplotlib bar-chart

我有covid19跟踪时间序列数据,这些数据是我从covid19跟踪站点截取的。我想制作一个带注释的分组堆积条形图。为此,我使用了matplotlibseaborn进行绘图,我想出了绘图数据来渲染相应的条形图。我尝试在SO中进行情节注释,但是没有获得正确的注释情节。另外,我还有一些问题需要对时间序列数据进行分组堆叠的条形图。有人可以建议这样做的可能方法吗?有想法吗?

我的尝试

这是我从covid19跟踪网站上抓取的reproducible time series data

import pandas as pd
from datetime import date
import matplotlib.pyplot as plt
import seaborn as sns

bigdf = pd.read_csv("coviddf.csv")
bigdf['run_date'] = pd.to_datetime(bigdf['run_date'])

for g, d in bigdf.groupby(['company']):
    data = d.groupby(['run_date','county-state', 'company', 'est'], as_index=True).agg({'new': sum, 'confirmed': sum, 'death': sum}).stack().reset_index().rename(columns={'level_4': 'type', 0: 'val'})
    print(f'{g}')
    g = sns.FacetGrid(data, col='est', sharex=False, sharey=False, height=5, col_wrap=4)
    g.map(sns.barplot, 'run_date', 'val', 'type', order=data.run_date.dt.date.unique(), hue_order=data['type'].unique())
    g.add_legend()
    g.set_xticklabels(rotation=90)
    g.set(yscale='log')
    plt.tight_layout()
    plt.show()

上述尝试有两个问题。我需要制作成组的堆叠条形图,其中每个组是每个不同的公司,并且每个堆叠条形图都是单独的机构(又名est中的coviddf.csv列),所以每个公司都可能有多个机构,所以我想查看分组堆积的条形图中新的,确认的和死亡的covid19病例数。有什么方法可以制作此时间序列的带注释的分组堆积条形图?谁能建议实现这一目标的可能方法?如何在一页上绘制这些图?有想法吗?

所需的输出

我试图像this postsecond related post那样制作成组的堆叠条形图。这是我要制作的带注释的分组堆积条形图:

enter image description here

有人能指出我如何通过以上尝试来实现这一目标吗?有什么想法吗?

2 个答案:

答案 0 :(得分:3)

分组条形图

  • 这并非您所要求的,但我认为这是一个更好的选择。
    • 这当然是一个更简单的选择。
    • 堆积条形图的问题在于public class Test{ static Test x= new Test(); public int tester() { return 5; } public static void main(String args[]) { x.tester(); } } 与其他值相比太大,以至于您将看不到confirmednew
  • 我认为此数据的最佳选择是水平条形图,每个deathcompany都有一组。
est

enter image description here

堆积条形图

    import pandas as pd # load the data df = pd.read_csv("https://gist.githubusercontent.com/jerry-shad/318595505684ea4248a6cc0949788d33/raw/31bbeb08f329b4b96605b8f2a48f6c74c3e0b594/coviddf.csv") df.drop(columns=['Unnamed: 0'], inplace=True) # drop this extra column # select columns and shape the dataframe dfs = df.iloc[:, [2, 3, 4, 12, 13]].set_index(['company', 'est']).sort_index(level=0) # display(dfs) confirmed new death company est Agri Co. 235 10853 0 237 CS Packers 630 10930 77 118 Caviness 675 790 5 19 Central Valley 6063A 6021 44 72 FPL 332 5853 80 117 # plot ax = dfs.plot.barh(figsize=(8, 25), width=0.8) plt.xscale('log') plt.grid(True) plt.tick_params(labelbottom=True, labeltop=True) plt.xlim(10**0, 1000000) # annotate the bars for rect in ax.patches: # Find where everything is located height = rect.get_height() width = rect.get_width() x = rect.get_x() y = rect.get_y() # The width of the bar is the count value and can used as the label label_text = f'{width:.0f}' label_x = x + width label_y = y + height / 2 # don't include label if it's equivalently 0 if width > 0.001: ax.annotate(label_text, xy=(label_x, label_y), va='center', xytext=(2, -1), textcoords='offset points') 相比,
  • newdeath几乎看不见。
confirmed

enter image description here

答案 1 :(得分:2)

我很难找到有关如何在matplotlib和后来的Plotly中创建GROUPED和STACKED条形图的信息。

这是我尝试解决您的问题的方法(使用Plotly):

# Import packages
import pandas as pd
from datetime import date
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

# Load data (I used the raw GitHub link so that no local file download was required)
bigdf = pd.read_csv("https://gist.githubusercontent.com/jerry-shad/318595505684ea4248a6cc0949788d33/raw/31bbeb08f329b4b96605b8f2a48f6c74c3e0b594/coviddf.csv")

# Get all companies names and number of companies
allComp = np.unique(bigdf.company)
numComp = allCompanies.shape[0]

# For all the companies
for i in range(numComp):
    # Grab company data and the names of the establishments for that company
    comp = allComp[i]
    compData = bigdf.loc[bigdf.company == comp]
    estabs = compData.est.to_numpy().astype(str)
    numEst = compData.shape[0]

    # Grab the new, confirmed, and death values for each of the establishments in that company
    newVals = []
    confirmedVals = []
    deathVals = []
    for i in range(numEst):
        estabData = compData.loc[compData.est == estabs[i]]
        newVals.append(estabData.new.to_numpy()[0])
        confirmedVals.append(estabData.confirmed.to_numpy()[0])
        deathVals.append(estabData.death.to_numpy()[0])

    # Load that data into a Plotly graph object
    fig = go.Figure(
        data=[
            go.Bar(name='New', x=estabs, y=newVals, yaxis='y', offsetgroup=1),
            go.Bar(name='Confirmed', x=estabs, y=confirmedVals, yaxis='y', offsetgroup=2),
            go.Bar(name='Death', x=estabs, y=deathVals, yaxis='y', offsetgroup=3)
        ]
    )

    # Update the layout (add time, set x/y axis titles, and bar graph mode)
    fig.update_layout(title='COVID Data for ' + comp, xaxis=dict(type='category'), xaxis_title='Establishment', 
                      yaxis_title='Value', barmode='stack')
    fig.show()

其中输出是每个公司的16个单独的Plotly图(它们是可交互的,并且可以缩放各种迹线,因为缩放新的/确认的/死亡的值并不容易)。 每个图在x轴上都有该公司的所有营业地点,并且每个营业地点的新/确认/死亡值都以堆积的条形图显示。

这是一个示例图: HBS Company COVID Data

我知道这并不能完全回答您的问题,但希望您对我的努力表示感谢:)