python - 如何使用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,并且阴影颜色将代表客户数量或每个任期实例的合同外。
解决方案
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()
,如果它只是快速而肮脏的绘图)。
推荐阅读
- android - 谷歌登录不适用于使用电容器生成的 ionic android 移动应用程序 - 抛出异常为 10
- reactjs - VS2019如何重启在本地构建时自动启动的npm
- android - 如何在对话框选择器中显示选定的日期?
- python-3.x - 得到 TypeError: Expected int32, got None of type 'NoneType' 相反
- .net - 在 .NET 正则表达式中,将零宽度正前瞻断言与其他搜索词结合起来
- javascript - Javascript:在将函数作为 arg 传递时携带“this”的上下文
- c++ - 为什么 DeviceIoControl IOCTL_DISK_GET_DRIVE_LAYOUT_EX 失败?
- python - 为什么我的嵌套循环没有继续到下一行代码?有人可以解释吗?
- reactjs - 传递 Prop 以使用 context 或 props 或 redux
- c++ - CTLineGetStringIndexForPosition 因 bad_alloc 而崩溃