基于D3.js实现分类多标签的Tree型结构可视化

xiaoxiao2025-11-19  6

全文共5270个字,4张图,预计阅读时间25分钟。

关键词: 可视化,D3.js,python,前端,代码

why

今天新来的实习生需要对部分分类文本进行多标签的检测,即根据已构建好的一、二级标签Excel文档,对众包平台人工标注的数据以及机器标注的数据进行评测。

此情此景,让我想起了曾经在实验做的文本多标签分类的工作,所以就想用Echart 或D3.js实现层级标签可视化为一个Tree的结构,方便实习生们查阅,提高工作效率。

说干就干!

How

处理数据

首先,找一个标准的基于D3.js实例程序,明确一下我们的工作目标以及步骤[数据的格式+前端代码]。

看一下需要将我们目前的结构化数据:

体育,篮球,NBA体育,篮球,CNA体育,篮球,CUBA体育,足球,中超体育,足球,欧冠体育,羽毛球体育,羽毛球,汤姆斯杯数码,手机,iPhone数码,手机,小米数码,电脑,MacPro数码,电脑,Dell数码,电脑,小米数码,照相机,索尼数码,照相机,尼康教育,大学,高数教育,大学,英语教育,高中,物理教育,高中,化学教育,高中,生物教育,小学教育,幼儿

标准的可以被D3.js加载的数据格式:

加载之后的Tree型结构效果图:

以上的Tree型图就是我们想要达到的目标。

我们需要将我们的数据,转换为D3.js可以加载的标准数据。

我决定使用python编写处理的脚本:编写的逻辑完全是自己瞎想的,如果各位有什么更好、更标准的方法,欢迎指出。

# coding:utf-8import sysreload(sys)sys.setdefaultencoding( "utf-8" )dic={}with open("testtag.txt"as f:for i in f:# print ii=i.split(",")k=str(i[0]).strip()if k not in dic:    dic[k]=[".".join(i[1:]).strip()]    # 是为了预防存在二级标签的缺失    dic[k].append(str(i[1]).strip())    # 又不能存在重复,使用set去重    dic[k]=list(set(dic[k]))else:    dic[k].append(str(i[1]).strip())    dic[k].append(".".join(i[1:]).strip())    dic[k]=list(set(dic[k]))with open("3tag.csv","w"as w:w.writelines("id,value"+'\n')w.writelines("3Tag"+'\n')for i in dic.keys():w.writelines("3Tag."+i+'\n')for j in dic[i]:      w.writelines("3Tag."+str(i)+"."+str(j).strip()+'\n')

处理之后的结果存储到本地的文件3tag.csv中:

一定要完全按照标准的D3.js的格式处理的。

id,value3Tag3Tag.体育3Tag.体育.篮球.CNA3Tag.体育.足球.中超3Tag.体育.篮球.CUBA3Tag.体育.篮球3Tag.体育.羽毛球3Tag.体育.足球3Tag.体育.羽毛球.汤姆斯杯3Tag.体育.篮球.NBA3Tag.体育.足球.欧冠3Tag.教育3Tag.教育.大学.高数3Tag.教育.高中3Tag.教育.幼儿3Tag.教育.高中.生物3Tag.教育.大学3Tag.教育.大学.英语3Tag.教育.高中.物理3Tag.教育.小学3Tag.教育.高中.化学3Tag.数码3Tag.数码.电脑.MacPro3Tag.数码.手机.小米3Tag.数码.照相机.索尼3Tag.数码.电脑.Dell3Tag.数码.手机.iPhone3Tag.数码.电脑.小米3Tag.数码.手机3Tag.数码.电脑3Tag.数码.照相机.尼康3Tag.数码.照相机

注意事项:

正确的数据:'''id,value3Tag3Tag.体育3Tag.体育.篮球3Tag.体育.篮球.CNA3Tag.体育.足球.中超3Tag.体育.足球'''1.处理数据的过程中要注意,不允许存在隔级的情况:eg:'''id,value3Tag3Tag.体育3Tag.体育.篮球.CNA'''*是错误,必须存在“3Tag.体育.篮球”这一级才可以,否则数据加载失败!

2.不允许存在重复的行数据,否则加载失败!'''id,value3Tag3Tag.体育3Tag.体育3Tag.体育.篮球.CNA'''

所以,整个处理的过程中,其实最麻烦的就是数据的处理了。

前端的web界面

标准数据有了,剩下的就是需要一个前端的web界面,这个代码在上面的示例页面中已经有了,只需要我们自己替换为我们的数据源就可以了,我还是贴出自己的代码吧。

<!DOCTYPE html><meta charset="utf-8"><style>.node circle {fill#999;}.node text {font10px sans-serif;}.node--internal circle {fill#555;}.node--internal text {text-shadow0 1px 0 #fff0 -1px 0 #fff1px 0 0 #fff,  -1px 0 0 #fff;}.link {fill: none;stroke#555;stroke-opacity0.4;stroke-width1.5px;}form {font-family"Helvetica Neue", Helvetica, Arial, sans-serif;position: absolute;left10px;top10px;}label {display: block;}</style><form><label><input type="radio" name="mode" value="cluster" checked> Dendrogram</label><label><input type="radio" name="mode" value="tree"> Tree</label></form><!-- <iframe  src="http://10.73.20.41/mblog_info_test/library3_quality_mbblog_line_tag_distrib/" width="1300" height="1900"   frameborder="0"  name=""     scrolling="yes">   </iframe> --><svg width="560" height="800"></svg><!-- <script src="d3.js"></script> --><script src="https://d3js.org/d3.v4.min.js"></script><script>var svg = d3.select("svg"),width = +svg.attr("width"),height = +svg.attr("height"),g = svg.append("g").attr("transform""translate(40,0)");var tree = d3.tree().size([height - 400, width - 160]);var cluster = d3.cluster().size([height, width - 160]);var stratify = d3.stratify().parentId(function(dreturn d.id.substring(0, d.id.lastIndexOf(".")); });d3.csv("3tag.csv"function(error, data{if (error) throw error;var root = stratify(data).sort(function(a, breturn (a.height - b.height) || a.id.localeCompare(b.id); });cluster(root);var link = g.selectAll(".link").data(root.descendants().slice(1)).enter().append("path").attr("class""link").attr("d", diagonal);var node = g.selectAll(".node").data(root.descendants()).enter().append("g").attr("class"function(dreturn "node" + (d.children ? " node--internal" : " node--leaf"); }).attr("transform"function(dreturn "translate(" + d.y + "," + d.x + ")"; });node.append("circle").attr("r"5);node.append("text").attr("dy"3).attr("x"function(dreturn d.children ? -8 : 8; }).style("text-anchor"function(dreturn d.children ? "end" : "start"; }).text(function(dreturn  d.id.substring(d.id.lastIndexOf(".") + 1); });d3.selectAll("input").on("change", changed);var timeout = setTimeout(function({d3.select("input[value=\"tree\"]").property("checked"true).dispatch("change");}, 1000);function changed({timeout = clearTimeout(timeout);(this.value === "tree" ? tree : cluster)(root);var t = d3.transition().duration(750);node.transition(t).attr("transform"function(dreturn "translate(" + d.y + "," + d.x + ")"; });link.transition(t).attr("d", diagonal);}});function diagonal(d{return "M" + d.y + "," + d.x+ "C" + (d.parent.y + 100) + "," + d.x+ " " + (d.parent.y + 100) + "," + d.parent.x+ " " + d.parent.y + "," + d.parent.x; }</script></body>

RESULT

最后,展示一下我们的成果:

以上就是本次层级标签可视化的实践,以后大家工作中再遇到多标签的问题,可以使用该方法快速的实现Tree型结构的可视化了,方便阅读与理解。

原文链接:https://www.jianshu.com/p/77708cfe3716

查阅更为简洁方便的分类文章以及最新的课程、产品信息,请移步至全新呈现的“LeadAI学院官网”:

www.leadai.org

请关注人工智能LeadAI公众号,查看更多专业文章

大家都在看

LSTM模型在问答系统中的应用

基于TensorFlow的神经网络解决用户流失概览问题

最全常见算法工程师面试题目整理(一)

最全常见算法工程师面试题目整理(二)

TensorFlow从1到2 | 第三章 深度学习革命的开端:卷积神经网络

装饰器 | Python高级编程

今天不如来复习下Python基础

转载请注明原文地址: https://www.6miu.com/read-5039914.html

最新回复(0)