首页 > 解决方案 > 如何使用python生成显示百分比而不是出现次数的图表?

问题描述

我有 1000 名客户,他们的任期和合同状态各不相同(1 表示他们在合同中,而 0 表示他们没有合同),如下面的数据框所示:

df = pd.DataFrame(columns = ['customer','tenure','contract_status'])
df['customer'] = np.arange(1001)
df['tenure'] = np.random.randint(1,200, df.shape[0]) 
df['contract_status'][:200] = 0
df['contract_status'][200:] = 1

我使用以下代码创建了一个直方图来说明客户在合同内外的分布:

sns.set_context('talk')
sns.set_style('darkgrid')
plt.rcParams["figure.figsize"] = (10,8)
plt.hist(df[df['contract_status'] == 1]['tenure'], bins = 50,alpha=0.5, label='Contract')
plt.hist(df[df['contract_status'] ==0]['tenure'], bins = 50, alpha=0.5, label='Non - contract')
plt.legend(loc='upper right')
plt.xlabel('tenure')
plt.title('Distribution of customers')
plt.show()

以下是我尝试过的示例和预期的解决方案:

> exp = df[(df['tenure']>0) & (df['tenure']<10)]

>  exp_plot = exp.groupby(['contract_status',
> 'tenure']).size().reset_index().pivot(columns='contract_status', index
> ='tenure', values=0)
>     exp_plot['In contract'] = ((exp_plot[1]/(exp_plot[0] + exp_plot[1])) * 100).round(2)
>     exp_plot['Out of contract'] = ((exp_plot[0]/(exp_plot[0] + exp_plot[1])) * 100).round(2)
>     exp_plot.drop([0,1],axis=1,inplace=True)

>     fig,ax = plt.subplots(figsize = (15,8))
>     exp_plot.plot(kind='bar',stacked=True,ax =ax)
>     ax.set(xlabel = 'tenure',ylabel='Percentage of customers',title= 'tenure' + 
>     by percentage',ylim=(0,100))
>     ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
>     
>     for p in ax.patches:
>         width, height = p.get_width(), p.get_height()
>         x, y = p.get_xy() 
>         ax.text(x+width/2,  y+height/2, '{:.1f}%'.format(height), 
>          horizontalalignment='center', 
>         verticalalignment='center',size=14,color='white')

此解决方案仅适用于少数数据点 - 如上所示,我仅将此示例用于 0 到 10 之间的任期。当我尝试将其应用于整个数据帧时,结果并不正确。

我想创建一个图形 - 类似于堆积条形图 - 以百分比而不是出现次数来显示分布,其中每个条形将上升到 1,并且阴影颜色将代表客户数量或每个任期实例的合同外。

标签: pythonmatplotlibhistogramseabornpercentage

解决方案


np.histogram()有一个density关键字,如果设置为True它会产生一个标准化的直方图。plt.hist()如果不支持相同的功能,我会感到惊讶。

修改应该足够了,例如:

plt.hist(df[df['contract_status'] == 1]['tenure'], bins = 50,alpha=0.5, label='Contract')

进入这个:

plt.hist(df[df['contract_status'] == 1]['tenure'], bins = 50, density=True, alpha=0.5, label='Contract')

(另外,也许你也应该考虑一下df.plot(),如果它只是快速而肮脏的绘图)。


推荐阅读