關(guān)鍵詞: 可視化,D3.js,python,前端,代碼
0.Why
今天新來的實習(xí)生需要對部分分類文本進(jìn)行多標(biāo)簽的檢測份名,即根據(jù)已構(gòu)建好的一舞蔽、二級標(biāo)簽Excel文檔芥驳,對眾包平臺人工標(biāo)注的數(shù)據(jù)以及機(jī)器標(biāo)注的數(shù)據(jù)進(jìn)行評測。
此情此景谭期,讓我想起了曾經(jīng)在實驗做的文本多標(biāo)簽分類的工作堵第,所以就想用Echart 或D3.js實現(xiàn)層級標(biāo)簽可視化為一個Tree的結(jié)構(gòu),方便實習(xí)生們查閱隧出,提高工作效率踏志。
說干就干!
1.How
1.1 處理數(shù)據(jù)
首先胀瞪,找一個標(biāo)準(zhǔn)的基于D3.js實例程序针余,明確一下我們的工作目標(biāo)以及步驟[數(shù)據(jù)的格式+前端代碼]。
看一下需要將我們目前的結(jié)構(gòu)化數(shù)據(jù):
體育,籃球,NBA
體育,籃球,CNA
體育,籃球,CUBA
體育,足球,中超
體育,足球,歐冠
體育,羽毛球
體育,羽毛球,湯姆斯杯
數(shù)碼,手機(jī),iPhone
數(shù)碼,手機(jī),小米
數(shù)碼,電腦,MacPro
數(shù)碼,電腦,Dell
數(shù)碼,電腦,小米
數(shù)碼,照相機(jī),索尼
數(shù)碼,照相機(jī),尼康
教育,大學(xué),高數(shù)
教育,大學(xué),英語
教育,高中,物理
教育,高中,化學(xué)
教育,高中,生物
教育,小學(xué)
教育,幼兒
標(biāo)準(zhǔn)的可以被D3.js加載的數(shù)據(jù)格式:
加載之后的Tree型結(jié)構(gòu)效果圖:
以上的Tree型圖就是我們想要達(dá)到的目標(biāo)凄诞。
我們需要將我們的數(shù)據(jù)圆雁,轉(zhuǎn)換為D3.js可以加載的標(biāo)準(zhǔn)數(shù)據(jù)。
我決定使用python編寫處理的腳本:
編寫的邏輯完全是自己瞎想的帆谍,如果各位有什么更好伪朽、更標(biāo)準(zhǔn)的方法,歡迎指出汛蝙。
# coding:utf-8
import sys
reload(sys)
sys.setdefaultencoding( "utf-8" )
dic={}
with open("testtag.txt") as f:
for i in f:
# print i
i=i.split(",")
k=str(i[0]).strip()
if k not in dic:
dic[k]=[".".join(i[1:]).strip()]
# 是為了預(yù)防存在二級標(biāo)簽的缺失
dic[k].append(str(i[1]).strip())
# 又不能存在重復(fù)烈涮,使用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')
處理之后的結(jié)果存儲到本地的文件3tag.csv中:
一定要完全按照標(biāo)準(zhǔn)的D3.js的格式處理的。
id,value
3Tag
3Tag.體育
3Tag.體育.籃球.CNA
3Tag.體育.足球.中超
3Tag.體育.籃球.CUBA
3Tag.體育.籃球
3Tag.體育.羽毛球
3Tag.體育.足球
3Tag.體育.羽毛球.湯姆斯杯
3Tag.體育.籃球.NBA
3Tag.體育.足球.歐冠
3Tag.教育
3Tag.教育.大學(xué).高數(shù)
3Tag.教育.高中
3Tag.教育.幼兒
3Tag.教育.高中.生物
3Tag.教育.大學(xué)
3Tag.教育.大學(xué).英語
3Tag.教育.高中.物理
3Tag.教育.小學(xué)
3Tag.教育.高中.化學(xué)
3Tag.數(shù)碼
3Tag.數(shù)碼.電腦.MacPro
3Tag.數(shù)碼.手機(jī).小米
3Tag.數(shù)碼.照相機(jī).索尼
3Tag.數(shù)碼.電腦.Dell
3Tag.數(shù)碼.手機(jī).iPhone
3Tag.數(shù)碼.電腦.小米
3Tag.數(shù)碼.手機(jī)
3Tag.數(shù)碼.電腦
3Tag.數(shù)碼.照相機(jī).尼康
3Tag.數(shù)碼.照相機(jī)
注意事項:
正確的數(shù)據(jù):
'''
id,value
3Tag
3Tag.體育
3Tag.體育.籃球
3Tag.體育.籃球.CNA
3Tag.體育.足球.中超
3Tag.體育.足球
'''
1.處理數(shù)據(jù)的過程中要注意窖剑,不允許存在隔級的情況:
eg:
'''
id,value
3Tag
3Tag.體育
3Tag.體育.籃球.CNA
'''
*是錯誤坚洽,必須存在“3Tag.體育.籃球”這一級才可以,否則數(shù)據(jù)加載失斘魍痢讶舰!
2.不允許存在重復(fù)的行數(shù)據(jù),否則加載失敗绘雁!
'''
id,value
3Tag
3Tag.體育
3Tag.體育
3Tag.體育.籃球.CNA
'''
所以橡疼,整個處理的過程中,其實最麻煩的就是數(shù)據(jù)的處理了庐舟。
1.2 前端的Web界面
標(biāo)準(zhǔn)數(shù)據(jù)有了欣除,剩下的就是需要一個前端的web界面,這個代碼在上面的示例頁面中已經(jīng)有了挪略,只需要我們自己替換為我們的數(shù)據(jù)源就可以了历帚,我還是貼出自己的代碼吧。
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.node circle {
fill: #999;
}
.node text {
font: 10px sans-serif;
}
.node--internal circle {
fill: #555;
}
.node--internal text {
text-shadow: 0 1px 0 #fff, 0 -1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff;
}
.link {
fill: none;
stroke: #555;
stroke-opacity: 0.4;
stroke-width: 1.5px;
}
form {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
position: absolute;
left: 10px;
top: 10px;
}
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(d) { return 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, b) { return (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(d) { return "node" + (d.children ? " node--internal" : " node--leaf"); })
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
node.append("circle")
.attr("r", 5);
node.append("text")
.attr("dy", 3)
.attr("x", function(d) { return d.children ? -8 : 8; })
.style("text-anchor", function(d) { return d.children ? "end" : "start"; })
.text(function(d) { return 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(d) { return "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>
2.RESULT
最后杠娱,展示一下我們的成果:
以上就是本次層級標(biāo)簽可視化的實踐挽牢,以后大家工作中再遇到多標(biāo)簽的問題,可以使用該方法快速的實現(xiàn)Tree型結(jié)構(gòu)的可視化了摊求,方便閱讀與理解禽拔。
我的博客即將搬運同步至騰訊云+社區(qū),邀請大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=3mtmis547ccgw