ermutuxia

2020-08-17   阅读量: 11113

python 画图 可视化 matplotlib 中文乱码

python中如何对一列数据进行分箱,分成个数比较均匀的几组样本,然后统计各组内的某个比率进行计算绘图。

扫码加入数据分析学习群

forver.xlsx

需求:我想等频分箱,就是比如一个score有不同的分数,先按照分数升序排列,排列后按照人数的分位数进行分箱,最终实现下图效果

image.png


数据下载链接网址https://bbs.pinggu.org/forum.php?mod=viewthread&tid=9485342&extra=

解答:

#------------------------------------------------------------
#导入数据
#--------------------------------------------------------------
import pandas as pd
import numpy as np
data1=pd.read_excel("D:\\forver.xlsx")

image.png

#计算分位数 0.2。。。,设定分箱区间
qq=data1["score1"].quantile([0.2,0.4,0.6,0.8])
min1=data1["score1"].min()
max1=data1["score1"].max()
intervel=[0]+list(qq)+[max1]

image.png

#对变量进行排序
data1.sort_values(by="score1",ascending=True,inplace=True)
#对相关变量进行分箱
data1["score1分箱l"]=pd.cut(data1.score1,intervel)
data1["score1分箱"]=pd.cut(data1.score1,intervel,labels=[1,2,3,4,5])

image.png

#---------------------------------------------------------------
#                准备画图用数据
#-----------------------------------------------------------------
#统计各箱包含的样本个数
#计算各箱的bad%
#说明target取值为1则为bad,0为good
score1各箱人数=data1["score1分箱l"].value_counts()
score1各箱人数.sort_index(inplace=True)
score1badcount=data1[data1["target"]==1]["score1分箱l"].value_counts()
score1goodcount=data1[data1["target"]==0]["score1分箱l"].value_counts()
#将几个指标按照索引进行横向合并
picdata=pd.concat([score1各箱人数,score1badcount,score1goodcount],axis=1)
picdata.columns=["score1各箱人数","score1badcount","score1goodcount"]
#计算各箱的bad%
picdata["badper"]=picdata["score1badcount"]/picdata["score1各箱人数"]
#

image.png

#---------------------------------------------------------------
#                      画图
#-------------------------------------------------------------------
xticklabel=[]
for i in range(len(intervel)-1):
    print(i)
    tt=str(int(intervel[i]))+"-"+str(int(intervel[i+1]))
    print(tt)
    xticklabel.append(tt)
import matplotlib.pyplot as plt
#解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['Simhei'] 
fig,ax1=plt.subplots()
ax1.bar(xticklabel,picdata["score1各箱人数"],label="坏人数",color='r',width=0.6)
ax1.bar(xticklabel,picdata["score1goodcount"],label="好人数",color='b',width=0.6)
ax1.set_ylim([0,300])  # y轴边界
ax1.legend(loc=2)
ax2=ax1.twinx()
ax2.plot(np.arange(5),picdata["badper"],'r',label="bad百分比")
ax2.set_ylim([0,1])  # y轴边界
ax2.legend(loc=1)
ax1.set_xticklabels(xticklabel,fontsize=20,rotation=45) 
fig.suptitle(u'score1的情况',fontsize=15)

image.png

添加CDA认证专家【维克多阿涛】,微信号:【cdashijiazhuang】,提供数据分析指导及CDA考试秘籍。已助千人通过CDA数字化人才认证。欢迎交流,共同成长!
0.2729 5 21 关注作者 收藏

评论(20)

wangxishi
2020-08-19

比如说我想用,'font.sans-serif'下的'Arial'这个字体,但是我这么改写代码后:

plt.rcParams['font.sans-serif'] = ['Arial']

运行会报错,是为什么呢?

1.png

0.0000 0 0 回复
ermutuxia
2020-08-18

问:柱状图及折线图的颜色可以更改吗?

答:我在下面这个帖子里回答了下

https://www.pinggu.com/post/details/5f3b5338922c1e31e64917fd

0.0000 0 0 回复
ermutuxia
2020-08-18

问:

plt.rcParams['font.sans-serif'] = ['Simhei']

请问这里面字体可以改吗?

答:

https://www.pinggu.com/post/details/5f3b4fb0922c1e31e64917f8

0.0000 0 0 回复
wangxishi
2020-08-18
plt.rcParams['font.sans-serif'] = ['Simhei']

请问这里面字体可以改吗?柱状图及折线图的颜色可以更改吗?

0.0000 0 0 回复
ermutuxia
2020-08-18

问:

您好,可以请教下,如果0一个箱子,1一个箱子,2一个箱子,这种情况,代码怎么写呢

答:
比如你的数据中score5这一列就是你说的这种情况,这种情况不需要分箱,直接看每个值出现的频数就行。
用下面的命令。


score5各箱人数=data1["score5"].value_counts()
score5各箱人数.sort_index(inplace=True)

image.png




score5badcount=data1[data1["target"]==1]["score5"].value_counts()
score5goodcount=data1[data1["target"]==0]["score5"].value_counts()
#将几个指标按照索引进行横向合并
picdata5=pd.concat([score5各箱人数,score5badcount,score5goodcount],axis=1)
picdata5.columns=["score5各箱人数","score5badcount","score5goodcount"]
#计算各箱的bad%
picdata5["badper"]=picdata5["score5badcount"]/picdata5["score5各箱人数"]

image.png

import matplotlib.pyplot as plt

#解决中文乱码问题

plt.rcParams['font.sans-serif'] = ['Simhei']

fig,ax1=plt.subplots()

#[0,1,2]是横轴的刻度线标签

ax1.bar([0,1,2],picdata5["score5各箱人数"],label="坏人数",color='r',width=0.6)

ax1.bar([0,1,2],picdata5["score5goodcount"],label="好人数",color='b',width=0.6)


ax1.set_ylim([0,600]) # y轴边界


ax1.legend(loc=2)


ax2=ax1.twinx()

ax2.plot(picdata5["badper"],'r',label="bad百分比")

ax2.set_ylim([0,1]) # y轴边界

ax2.legend(loc=1)

fig.suptitle(u'score5的情况',fontsize=15)

image.png

0.0000 0 0 回复
wangxishi
2020-08-18

您好,可以请教下,如果0一个箱子,1一个箱子,2一个箱子,这种情况,代码怎么写呢

0.0000 0 0 回复
ermutuxia
2020-08-18

问:

还有个关于等频分箱的问题想请教您:如果x变量里面有空值和0,0在这里面也是有意义的值,并且空值和0的比例占比较大,这种情况下还可以用等频分箱吗?如果想继续用等频分箱,要对数据如何处理呢

答:

1.如果你的数据的取值比较少的话比如0值占了50%,1占了20%,2占了30%,也就是说数据取值个数比较少,那你直接画频数图就行,不用分箱了,因为本身就算是几个箱子,0是一个箱子,1是一个箱子,2是一个箱子。

image.png


2.如果你的 数据的取值比较多的话比如0值占了50%,而其他值的取值区间为1-100,你可以将0值单独作为一类,其他值再进行分箱画图

image.png

0.0000 0 0 回复
wangxishi
2020-08-18

还有个关于等频分箱的问题想请教您:如果x变量里面有空值和0,0在这里面也是有意义的值,并且空值和0的比例占比较大,这种情况下还可以用等频分箱吗?如果想继续用等频分箱,要对数据如何处理呢

0.0000 0 0 回复
ermutuxia
2020-08-17
问:ax2=ax1.twinx()#产生一个ax1的镜面坐标
ax2.plot(np.arange(5),picdata["badper"],'r',label="bad百分比")#第一个参数是横轴的刻度线标签

这两行代码的作用是添加了折线图对吧,这块python是怎么识别出来是折线图的呢,还是这个plot函数自动生成的就是折现图?谢谢!

答:是的ax2.plot就是画折线图,ax1.bar就是画柱形图

0.0090 1 0 回复
ermutuxia
2020-08-17
问:score1各箱人数.sort_index(inplace=True)

这步是做什么用呢?

答:作用是对score1序列进行排序,排序前是这样的

image.png

排序后

image.png

inplace=True的意思是直接作用于score1各箱人数,而不是临时排序。


0.0090 1 0 回复
wangxishi
2020-08-17

2.png

为什么i第一次循环的时候是从0开始到5,第二次循环就可以从5开始 到7?第二次循环不会再从0开始吗?

0.0000 0 0 回复
wangxishi
2020-08-18

因为i是从0开始循环的,在0的时候,取出的数是0-5,接下来循环到1,取出的数是5-7,大概明白了

0.0000 0 0 回复
wangxishi
2020-08-17
score1各箱人数.sort_index(inplace=True)

这步是做什么用呢

0.0000 0 0 回复
wangxishi
2020-08-17
ax2=ax1.twinx()#产生一个ax1的镜面坐标
ax2.plot(np.arange(5),picdata["badper"],'r',label="bad百分比")#第一个参数是横轴的刻度线标签

这两行代码的作用是添加了折线图对吧,这块python是怎么识别出来是折线图的呢,还是这个plot函数自动生成的就是折现图?谢谢!

0.0000 0 0 回复
wangxishi
2020-08-17

1.png感谢解答!目前还有这三个不太理解 ! 谢谢!

0.0000 0 0 回复
ermutuxia
2020-08-17

image.png

fig.suptitle(u'score1的情况',fontsize=15) 是给图纸fig添加一个标题,你可以根据需要自行修改标题的内容。fontsize是设定这个标题的字号大小。

0.0000 0 0 回复
ermutuxia
2020-08-17

问题框1:

fig,ax1=plt.subplots()

这个的意思是生成一张图纸fig,和一个坐标系ax1。

问题框2:

ax1.legend(loc=2) 是给坐标系ax1添加图例,loc参数用于设定添加图例的位置。数值意思如下

and each "string" locations can also be given as a

numeric value:

=============== =============

Location String Location Code

=============== =============

'best' 0

'upper right' 1

'upper left' 2

'lower left' 3

'lower right' 4

'right' 5

'center left' 6

'center right' 7

'lower center' 8

'upper center' 9

'center' 10

=============== =============

问题框3:

ax2.plot(np.arange(5),picdata["badper"],'r',label="bad百分比")

里面的第一个参数是横轴的刻度线标签,你可以把这个刻度线标签直接设定为

ax2.plot(xticklabel,picdata["badper"],'r',label="bad百分比")

问题框4:

ax2.legend(loc=1)

给坐标系ax2添加图例

问题框5:

ax1.set_xticklabels(xticklabel,fontsize=20,rotation=45)

设定横轴刻度线标签的字号为20,旋转45度,是怕标签太长,然后多个标签可能会重叠在一起。

0.0000 0 0 回复
wangxishi
2020-08-17

1.jpg不理解的地方我都用红框标出了,辛苦解释下代码意思,然后剩下我已写注释的您看下是否正确,谢谢!

0.0000 0 0 回复
ermutuxia
2020-08-17


先看下intervel里面的内容是什么样的

image.png

然后生成一个空白列表

xticklabel=[]

然后通过循环给空白列表xticklable添加元素。下面的循环是一个整体,一定不要分开去运行。


image.png

这是一个完整的循环,经过这一次循环,xticklabe列表就会追加一个元素,执行完上面的命令再看下xticklabel

xticklabel

Out[111]: ['0-5', '5-7', '7-11', '11-17', '17-46']

生成这个列表是为了画图的时候,将这个列表作为横轴的刻度标签使用。

0.0000 0 0 回复
wangxishi
2020-08-17

为什么i第一次循环的时候是从0开始到5,第二次循环就可以从5开始 到7?第二次循环不会再从0开始吗?

0.0000 0 0 回复
ermutuxia
2020-08-17

image.png

data1["score1分箱l"].value_counts()


image.png

这个命令的意思是对score1分箱1这个变量里面的每个数值进行统计,看每个数值出现了多少次

你看下这个问题你明白了没有

0.0000 0 0 回复
wangxishi
2020-08-17
score1各箱人数.sort_index(inplace=True)

这步是什么作用呢

0.0000 0 0 回复
wangxishi
2020-08-17
for i in range(len(intervel)-1):

这行代码怎么理解呢,这里面

intervel的值怎么出来的



0.0000 0 0 回复
wangxishi
2020-08-17
score1各箱人数=data1["score1分箱l"].value_counts()
score1各箱人数.sort_index(inplace=True)

这两步过后为什么就能看到每箱人数了呢?

0.0000 0 0 回复

推荐课程

推荐帖子