梁先国SEO专注网站优化,让您网站更具价值!

当前位置:首页 > WEB前端学习 > 如何采用python和D3.js展示多级技术分支【实战作图详解】

如何采用python和D3.js展示多级技术分支【实战作图详解】

时间:2018-08-10 11:47 来源:重庆网站制作公司(www.seozol.cn) 作者:重庆网站建设公司

圆堆积图(Circle Packing)也称为“圆形树结构图”,是树形结构图的变体,使用圆形一层又一层地代表整个层次结构。每个圆形的面积可用来表示数值的大小。还可用颜色将数据进行分类。
 
在专利分析中,圆堆积图可以用于表示某一领域的技术构成,圆圈的嵌套层级可以展示多级技术分支之间的包含关系,圆圈的大小体现了该分支内的专利量的多少。
 
今天,梁先国网络科技小编尝试采用python和D3.js制圆堆积图来展示多级技术分支的可视化。
 
为了使用D3绘图,首先用文本编辑器建立一个网页文件:复制下面的程序至Sublime Text(不想装Sublime Text的小伙伴用windows的记事本等编辑器也可以)另存为.html文件,在网页文件中引用D3绘图库绘制,点击浏览器打开即可看到图表或者debug程序。
 
建立网页的过程涉及到专业的前端设计知识,为了减少工作量,我们直接修改模板即可。本篇教程的网页代码如下:
 
<!DOCTYPE html>
 
<meta charset="utf-8">
 
<style>
 
circle {
 
  fill: rgb(31, 119, 180);
 
  fill-opacity: .25;
 
  stroke: rgb(31, 119, 180);
 
  stroke-width: 1px;
 
 
.leaf circle {
 
  fill: #ff7f0e;
 
  fill-opacity: 1;
 
 
text {
 
  font: 10px sans-serif;
 
  text-anchor: middle;
 
}
 
</style>
 
<svg width="960" height="960"></svg>
 
<script src="https://d3js.org/d3.v4.min.js"></script>
 
<script> 
 
var svg = d3.select("svg"),
 
   diameter = +svg.attr("width"),
 
    g = svg.append("g").attr("transform", "translate(2,2)"),
 
   format = d3.format(",d"); 
 
var pack = d3.pack()
 
   .size([diameter - 4, diameter - 4]);
 
d3.json("flare.json", function(error, root) {
 
  if (error) throw error; 
 
  root = d3.hierarchy(root)
 
     .sum(function(d) { return d.size; })
 
     .sort(function(a, b) { return b.value - a.value; });
 
  var node = g.selectAll(".node")
 
   .data(pack(root).descendants())
 
   .enter().append("g")
 
     .attr("class", function(d) { return d.children ? "node" : "leaf node"; })
 
     .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); 
 
  node.append("title")
 
     .text(function(d) { return d.data.name + "\n" + format(d.value); });
 
  node.append("circle")
 
     .attr("r", function(d) { return d.r; }); 
 
  node.filter(function(d) { return !d.children; }).append("text")
 
     .attr("dy", "0.3em")
 
     .text(function(d) { return d.data.name.substring(0, d.r / 3); });
 
});
 
</script>
 
 
对上述开源模版做如下修改,即可得到我们的多级技术分支的Circle Packing图啦:
 
 

多级技术分支的Circle Packing图
1. 颜色及字体修改
 
枝干(外层圆)颜色,通过下述语句中的fill字段修改RGB值,可接受RGB或24位16进制颜色值:
 
circle {
 
  fill: rgb(31, 119, 180);
 
  fill-opacity: .25;
 
  stroke: rgb(31, 119, 180);
 
  stroke-width: 1px;
 
}
 
叶子(内层圆)的颜色,通过下述语句中的fill字段修改即可:
 
.leaf circle {
 
  fill: #ff7f0e;
 
  fill-opacity: 1;
 
}
 
标签的字体及大小,通过下述语句中的font字段进行修改:
 
text {
 
  font: 10px sans-serif;
 
  text-anchor: middle;
 
}
 
 
 
2. 输入数据格式转换
 
D3是基于javascript语言编写的,数据是以json格式喂给D3的,因此我们需要将在技术分解时一般常用的Excel格式的数据转换为json格式。 
 
用于绘制circle packing的json数据是一种树状结构,即由一个主干,向上发散出多个枝干,枝干向上再发散出多个叶子。用于数据输入的Excel文件如下图所示,也是一种树状结构。需要注意的是,当某个枝干没有下一级枝干或者叶子时,需要我们填入“无”以供程序区分,例如表中的“装置”分类。
 
我们使用一段python程序来将这个excel表格转换为json文件(也可以通过Excel的一个收费小插件‘Excel to JSON’转换为json文件),待读入数据可以是如下图所示的Excel文件:
 
 
Excel转为json格式的python程序如下所示:
 
import pandas as pd 
 
xl = pd.ExcelFile('数据.xlsx')
 
df=xl.parse('工作表1')
 
df1=df.fillna(method='pad')
 
node={"name":"","children":[]}
 
leaf={"name":"","size":0}
 
result=[]
 
name_list=[] 
 
for i in df1.index:
 
   if df1.iloc[i][0] not in name_list:
 
        name_list.append(df1.iloc[i][0])
 
        node={"name":df1.iloc[i][0],"children":[]}
 
        result.append(node)
 
   else:
 
        pass 
 
name_list2=[]
 
for i in df1.index:
 
   name1=df1.iloc[i][0]
 
   name2=df1.iloc[i][1]
 
   if name2 not in name_list2:
 
        name_list2.append(name2)
 
        node={"name":name2,"children":[]}
 
        for i in result:
 
            if i['name']==name1:
 
                i["children"].append(node)
 
            else:
 
                pass
 
   else:
 
        pass 
 
name_list3=[]
 
for i in df1.index:
 
   name1=df1.iloc[i][0]
 
   name2=df1.iloc[i][1]
 
   name3=df1.iloc[i][2]
 
   if name3 not in name_list3:
 
        if name3=='无':
 
            name3=name2
 
        name_list3.append(name3)
 
        node={"name":name3,"children":[]}
 
        for i in result:
 
            if i['name']==name1:
 
                for j in i["children"]:
 
                    if j["name"]==name2:
 
                        j["children"].append(node)
 
            else:
 
                pass
 
   elif name3=='无':
 
        name3=name2
 
        node={"name":name3,"children":[]}
 
        for i in result:
 
            if i['name']==name1:
 
                for j in i["children"]:
 
                    if j["name"]==name2:
 
                        j["children"].append(node)
 
            else:
 
                pass
 
   else:
 
        pass
 
name_list4=[]
 
for i in df1.index:
 
   name1=df1.iloc[i][0]
 
   name2=df1.iloc[i][1]
 
   name3=df1.iloc[i][2]
 
   name4=df1.iloc[i][3]
 
   if name4 not in name_list4:
 
        if name4=='无':
 
            if name3=='无':
 
                name4=name2
 
                name3=name2
 
            else:
 
                name4=name3
 
        name_list4.append(name4)
 
        leaf={"name":name4,"size":df1.iloc[i][4]}
 
        print(leaf)
 
        print('name:',(name1,name2,name3,name4))
 
        for i in result:
 
            if i['name']==name1:
 
                for j in i["children"]:
 
                    if j["name"]==name2:
 
                        for k in j['children']:
 
                            if k['name']==name3:
 
                                k["children"].append(leaf)
 
                                print('add:',leaf)
 
            else:
 
                pass
 
   elif name4=='无':
 
        if name3=='无':
 
            name4=name2
 
            name3=name2
 
        else:
 
            name4=name3
 
        leaf={"name":name4,"size":df1.iloc[i][4]}
 
        print('else:',leaf)
 
        print('name:',(name1,name2,name3,name4))
 
        for i in result:
 
            if i['name']==name1:
 
                for j in i["children"]:
 
                    if j["name"]==name2:
 
                        for k in j['children']:
 
                            if k['name']==name3:
 
                                k["children"].append(leaf)
 
            else:
 
                pass
 
   else:
 
        pass 
 
out=str(result[0])
 
out=out.replace("'","\"")
 
with open('flare.json', 'w') as fout:
 
   fout.write(out)
 
 
适应性的修改上述程序中读入的excel及其sheet的名称,执行程序,于是在python程序所在目录下生成flare.json文件。将该文件和网页模板文件放在同一目录下,双击该网页文件打开圆堆积图:
 
 
生成flare.json文件,打开圆堆积图
 
写给使用IE、Chrome和360浏览器的小伙伴们:
 
默认情况下IE、Chrome和360浏览器可能无法正常显示这个图表(经测试,火狐浏览器是可以直接打开正常显示的,其他浏览器小编并没有装),这是因为浏览器的安全限制问题。为了让用IE和Chrome浏览器的小伙伴正常打开D3绘制的图表,我们需要进行一些额外的操作。
 
首先,打开Anaconda prompt(打开方式参见:作图详解|Anaconda扩展包的安装及bug处理),切换到存放D3网页和json数据的文件夹下。例如小编的文件夹在“C:\Users\lamapig\Desktop\D3”下,而Anaconda prompt打开后默认的目录是“C:\Users\lamapig\Documents”,我们怎么进到D3的文件夹呢?输入命令“cd C:\Users\lamapig\Desktop\D3”就可以啦!然后,使用“dir”命令查看一下文件夹内的文件,确认进入了正确的路径:
 
使用“dir”命令查看一下文件夹内的文件
 
确认一切正常后,在这一路径下,继续输入命令“python -m http.server 8989”来启动一个简易的web服务器。
 
启动后,可以在任意一个浏览器的地址栏里输入http://localhost:8990/来进入网页查看目录下的文件,单击下图目录中的circle_packing.html就可以得到我们刚刚画的图啦。


浏览器的地址栏里输入http://localhost:8990/




 
 
 
本文标签:

版权声明:本文:如何采用python和D3.js展示多级技术分支【实战作图详解】 由重庆网站制作公司(www.seozol.cn)原创内容,如需要转载请注明原文网址:重庆网站建设公司http://www.seozol.cn/

 
喜欢看,就分享到:

围观: 9999次 | 责任编辑:重庆网站建设公司

推荐文章

热门文章

最新文章

回到顶部