在 Jupyter Notebook 上清理并制作可读的条形图

Posted

技术标签:

【中文标题】在 Jupyter Notebook 上清理并制作可读的条形图【英文标题】:Clean and make readable bar graphs on Jupyter Notebook 【发布时间】:2020-02-26 11:44:03 【问题描述】:

这可能是小事,但我怎样才能使我的条形图输出可读。显然,我需要删除条形高度上的 +sign 以及 小数,以便我只保留整数。这是我的数据:

# intialise data of lists. 
data = 'Hospital_name':['Jootrh Hospital', 'Jootrh Hospital', 'Embu Hospital', 'Embu Hospital','Bungoma Hospital', 'Bungoma Hospital', 'Keru Hospital', 'Keru Hospital'], 
        'periodname':["18-Jul", "18-Aug", "18-Jul", "18-Aug","18-Jul", "18-Aug", "18-Jul", "18-Aug"], 'normal deliveries':[452, 458, "NAN", 45,498, 466, "NAN", 450],
       'caesarian sections':[67.0, 99.0, 13.0, 13.0,60.0, 19.0, 73.0, "NAN"], 'breach delivery':[10.0, "NAN", 13.0, 137.0,100.0, "NAN", "NAN" ,197.0],
       'assisted vd':["NAN", "NAN", 1.0, 37.0,1.0, "NAN", 1.0, 37.0]


# Create DataFrame 
df = pd.DataFrame(data) 
df

这是我的代码,我正在使用 jupyter notebook:

import numpy as np
import matplotlib.pyplot as plt
grouped = df.groupby('Hospital_name')

ncols=1
nrows = int(np.ceil(grouped.ngroups/ncols))

fig, axes = plt.subplots(nrows=nrows, ncols=ncols,figsize=(10,40),  constrained_layout=True)

x_offset = 0.02
y_offset = 0.02

for (key, ax) in zip(grouped.groups.keys(), axes.flatten()):

    temp = grouped.get_group(key).replace("NAN",0).plot(kind='bar',ax=ax, title=key)
    for bar in temp.patches:
        b = bar.get_bbox()
        val = ":+.2f".format(b.y1 + b.y0)        
        ax.annotate(val, ((b.x0 + b.x1)/2 + x_offset, b.y1 + y_offset))


ax.legend()
plt.show()

这是我的输出,看起来很乱

有人可以帮助我的输出看起来可读吗?请注意,我确实需要那些条形高度数字,最终结果将保存在可能是 pdf 的文档中。 +号和小数可以去掉

【问题讨论】:

一些想法。您可以使用tick_params (matplotlib.org/3.1.1/api/_as_gen/…) 旋转xticklabels,您可以使用tight_layout (matplotlib.org/3.1.1/api/_as_gen/…) 改进图形的布局,并使用subplots_adjust (matplotlib.org/3.1.1/api/_as_gen/…) 进一步调整子图周围的空间,您可以使图形更宽带 figsize(第一个值宽度,第二个值高度)。 @Patol75 您是否可以复制它的样本。我已经尝试了一些选项,但似乎我错过了一些东西 【参考方案1】:

这样的东西对你有用吗?我知道这是很多变化,并且与我的评论并不完全一致,但这就是我发现的方式。我还意识到您可能需要进行一些调整以适应您拥有的所有其他日期。

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

data = 'Name': ['Jootrh Hospital', 'Jootrh Hospital',
                 'Embu Hospital', 'Embu Hospital',
                 'Bungoma Hospital', 'Bungoma Hospital',
                 'Keru Hospital', 'Keru Hospital'],
        'Date': ['18-Jul', '18-Aug', '18-Jul', '18-Aug', '18-Jul', '18-Aug',
                 '18-Jul', '18-Aug'],
        'Norm_Del': [452, 458, np.nan, 45, 498, 466, np.nan, 450],
        'Caesa_Sec': [67., 99., 13., 13., 60., 19., 73., np.nan],
        'Br_Del': [10., np.nan, 13., 137., 100., np.nan, np.nan, 197.],
        'Ass_VD': [np.nan, np.nan, 1., 37., 1., np.nan, 1., 37.]
df = pd.DataFrame(data)
df2 = df.pivot_table(
    values=['Norm_Del', 'Caesa_Sec', 'Br_Del', 'Ass_VD'],
    index=['Name', 'Date'], fill_value=0)
df2.plot.bar(rot=45, figsize=(16, 8),
             color=['xkcd:cerulean', 'xkcd:avocado', 'xkcd:silver',
                    'xkcd:purple'])
i = 0
for unused, rows in df2.iterrows():
    print(rows['Norm_Del'])
    plt.annotate(rows['Ass_VD'], xy=(i - 0.19, rows['Ass_VD'] + 5), rotation=0,
                 color='xkcd:cerulean', fontweight='semibold', ha='center')
    plt.annotate(rows['Br_Del'], xy=(i - 0.06, rows['Br_Del'] + 5), rotation=0,
                 color='xkcd:avocado', fontweight='semibold', ha='center')
    plt.annotate(rows['Caesa_Sec'], xy=(i + 0.06, rows['Caesa_Sec'] + 5),
                 rotation=0, color='xkcd:silver', fontweight='semibold',
                 ha='center')
    plt.annotate(rows['Norm_Del'], xy=(i + 0.19, rows['Norm_Del'] + 5),
                 rotation=0, color='xkcd:purple', fontweight='semibold',
                 ha='center')
    i += 1
plt.savefig('so.png', bbox_inches='tight')
plt.show()

编辑:

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

data = 'Name': ['Jootrh Hospital', 'Jootrh Hospital',
                 'Embu Hospital', 'Embu Hospital',
                 'Bungoma Hospital', 'Bungoma Hospital',
                 'Keru Hospital', 'Keru Hospital'],
        'Date': ['18-Jul', '18-Aug', '18-Jul', '18-Aug', '18-Jul', '18-Aug',
                 '18-Jul', '18-Aug'],
        'Norm_Del': [452, 458, np.nan, 45, 498, 466, np.nan, 450],
        'Caesa_Sec': [67., 99., 13., 13., 60., 19., 73., np.nan],
        'Br_Del': [10., np.nan, 13., 137., 100., np.nan, np.nan, 197.],
        'Ass_VD': [np.nan, np.nan, 1., 37., 1., np.nan, 1., 37.]
df = pd.DataFrame(data)
df2 = df.pivot_table(
    values=['Norm_Del', 'Caesa_Sec', 'Br_Del', 'Ass_VD'],
    index=['Name', 'Date'], fill_value=0)
names = np.unique([x[0] for x in df2.index.values])
dates = sorted(np.unique([x[1] for x in df2.index.values]),
               key=lambda day: datetime.strptime(day, '%d-%b'))
values = df2.columns.values
locLab = [-0.19, -0.06, 0.06, 0.19]
colors = ('xkcd:cerulean', 'xkcd:avocado', 'xkcd:silver', 'xkcd:purple')
fig, axs = plt.subplots(nrows=names.shape[0], figsize=(5 * len(dates),
                                                       4 * names.shape[0]))
i = 0
for name in names:
    df2.loc[name].reindex(dates).plot.bar(
        rot=0, ax=axs[i], title=name, color=colors)
    j = 0
    for date in dates:
        k = 0
        maxVal = np.amax(df2.loc[name].values)
        for value in values:
            val = df2.loc[name].loc[date][value]
            axs[i].annotate(val, xy=(j + locLab[k], val + maxVal / 100),
                            color=colors[k], fontweight='semibold',
                            ha='center')
            k += 1
        j += 1
    i += 1
plt.tight_layout()
plt.savefig('so.png', bbox_inches='tight')

【讨论】:

完美的只是稍微改动一下,这样我就可以让每个医院名称都有自己的图表,你能更新代码给每个医院自己的图表吗? 然后我的输出栏高度数给出了一个非常长的十进制数,例如 452.05263157894734,我在想我是否也可以将其缩短为整数 452

以上是关于在 Jupyter Notebook 上清理并制作可读的条形图的主要内容,如果未能解决你的问题,请参考以下文章

Windows10 环境下Jupyter Notebook的安装与使用

Jupyter notebook 是什么

Jupyter notebook 是什么

上手jupyter notebook神器

Python 和 Matplotlib:在 Jupyter Notebook 中制作交互式 3D 绘图

jupyter notebook 安装教程