报错:
AttributeError: unexpected attribute 'legend_field' to VBar, possible attributes are bottom, fill_alpha...
bokeh在低版本中1.34中使用legend和高版本是不一样的,在2.4.X中可以用legend_field='label'
,但是在低版本中需要使用legend='label'
源代码:
import csv
from bokeh.palettes import d3
from bokeh.layouts import column
from bokeh.models import ColumnDataSource,FactorRange
from bokeh.plotting import figure, output_file, show
from bokeh.transform import factor_cmap
def plot_recall_precison(csv_path,html_path):
# 读取csv至字典
csvFile = open(csv_path, "r")
reader = csv.reader(csvFile)
# 建立空列表
result = {}
recall_title='Recall Rate:'
precision_title='Precision Rate:'
#csv文件的行数
lines = len(open(csv_path).readlines())
for item in reader:
# 忽略第一行,reader对象其实就是由CSV文档的多行数据构成的,每行数据会有一个属性:line_num表示行
if reader.line_num == 1:
# print(item[len(item)-1])
recall_title =recall_title+str(round(float(item[len(item)-1])*100,4))+'%'
continue
#忽略最后统计数量的两行
if reader.line_num < lines-1:
result[item[0]]=item[1:len(item)-1]
#倒数第二行是召回率
if reader.line_num == lines-1:
precision_title = precision_title+str(round(float(item[0])*100,4))+'%'
csvFile.close()
#把字典的key转换为列表
keys = list(result.keys())
#复制列表的函数[1,2,3]->[1,1,2,2,3,3]
def double_list(list1):
l2 =[]
for i in list1:
l2.append(i)
l2.append(i)
return l2
#类别名称
categorys = ['total','recall']
categorys_pre = ['total','precision']
#codes的数量和召回数量
total_count = []
recall_count = []
#codes名称
codes = []
#legend图例的分组
labels = []
#转换字符为数字类型, '0123': ['54.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '0.0', '1.0']
# 变为'0123': [54.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]
# 建立精准率的空列表
precision_totalcount = [0]*len(result)
i = 0
for item in result.items():
result[item[0]] = [float(x) for x in result[item[0]]]
total_count.append(sum(result[item[0]]))
codes.append(item[0])
labels.append(item[0])
labels.append(item[0])
precision_totalcount = list(map(lambda a,b:a+b,precision_totalcount,result[item[0]]))
recall_count.append(float(item[1][i]))
# print(item[0],item[1],item[1][i])
i = i +1
print('*'*10)
# print(result)
print(result.keys())
# print('total_count',total_count)
# print('codes',codes*2)
# print('recall_count',recall_count)
# print('precision_totalcount',precision_totalcount)
# print('labels',labels)
hover_totalcount = double_list(total_count)
hover_recallcount = double_list(recall_count)
hover_recallrate = list(map(lambda a,b : round(a/b,4) if b !=0 else 0,hover_recallcount,hover_totalcount))
hover_precision_tatalcount = double_list(precision_totalcount)
hover_precision_rate = list(map(lambda a,b : round(a/b,4) if b !=0 else 0,hover_recallcount,hover_precision_tatalcount))
print(hover_recallrate)
print(hover_precision_rate)
data = {'codes':codes,
'total':total_count,
'recall':recall_count,
'pre_total':precision_totalcount}
# create [('0123', 'total'), ('0123', 'recall'), ('1101', 'total'), ('1101', 'recall')
x = [ (code, category) for code in codes for category in categorys ]
x_pre = [ (code, category) for code in codes for category in categorys_pre]
counts = sum(zip(data['total'], data['recall']), ()) # like an hstack
counts_pre = sum(zip(data['pre_total'], data['recall']), ()) # like an hstack
source = ColumnDataSource(data=dict(x=x, counts=counts,label=labels,
hover_recallcount=hover_recallcount,hover_totalcount=hover_totalcount,hover_recallrate=hover_recallrate))
source_pre = ColumnDataSource(data=dict(x_pre=x_pre, counts_pre=counts_pre,label=labels,
hover_recallcount=hover_recallcount,hover_precision_tatalcount=hover_precision_tatalcount,hover_precision_rate=hover_precision_rate))
TOOLTIPS = [
("Total", "@hover_totalcount"),
("Recall", "@hover_recallcount"),
('Recall Rate',"@hover_recallrate")
]
TOOLTIPS_PRE = [
("Total", "@hover_precision_tatalcount"),
("Recall", "@hover_recallcount"),
('Precision Rate', "@hover_precision_rate")
]
output_file(html_path)
color_palette = d3['Category20'][20]+d3['Category20c'][20]
#toolbar_location=None为不显示自带的那些功能,tools=""表示柱状图是不可以拖动改变的
p = figure(x_range = FactorRange(*x),height=300,width=1000,tooltips=TOOLTIPS,
title=recall_title,toolbar_location=None,tools="")
#使用color映射条形颜色,其中调色板用d3 https://docs.bokeh.org/en/latest/docs/reference/palettes.html?highlight=viridis
p.vbar(x='x', top='counts', width=0.9, bottom=0, color= factor_cmap('x', palette=color_palette[0:len(counts)],
factors=x),legend='label',source=source)
#toolbar_location=None为不显示自带的那些功能,tools=""表示柱状图是不可以拖动改变的
p_pre= figure(x_range = FactorRange(*x_pre),height=300,width=1000,tooltips=TOOLTIPS_PRE,
title=precision_title,toolbar_location=None,tools="")
p_pre.vbar(x='x_pre', top='counts_pre', width=0.9, bottom=0, color= factor_cmap('x_pre', palette=color_palette[0:len(counts_pre)],
factors=x_pre),legend='label',source=source_pre)
#y的起始坐标是从0开始
p.y_range.start = 0
p.y_range.end = max(total_count)+100
#x的起始柱状图距离原点的距离
p.x_range.range_padding = 0.1
p.xaxis.major_label_orientation = 0.5
#网格线设置为无
p.xgrid.grid_line_color = None
#legend图例水平且居中
p.legend.orientation = "horizontal"
p.legend.location = "top_center"
# 去除网格线
p.grid.visible = False
##精准率的
#y的起始坐标是从0开始
p_pre.y_range.start = 0
p_pre.y_range.end = max(total_count)+100
#x的起始柱状图距离原点的距离
p_pre.x_range.range_padding = 0.1
p_pre.xaxis.major_label_orientation = 0.5
#网格线设置为无
p_pre.xgrid.grid_line_color = None
#legend图例水平且居中
p_pre.legend.orientation = "horizontal"
p_pre.legend.location = "top_center"
# 去除网格线
p_pre.grid.visible = False
show(column(p,p_pre))
if __name__ == '__main__':
csv_path = r"H:\B1project\Fastercnn_result\confusion_matrix调阈值\test.csv"
html_path = r'H:\recall_pre.html'
plot_recall_precison(csv_path,html_path)