D3.js數據可視化(二)——繪制弦圖(Chord Layout)


樹圖網可視化實驗

1. 實驗要求

  要求通過樹,或者圖、網的可視化聚類,分析某個公司的郵件社交網絡。根據要求設計可視化方案,並利用D3工具實現可視化效果。

2. 過程

2.1. 可視化方案的設計思路

2.1.1. 可視化要求

  1) 可視化該郵件社交網絡。

  2) 該可視化中的每個Edge都對應着一個權重(Emails per month或者weight),要求將該權重屬性映射到一個圖形化的屬性,比如,color,types of line,size or shapes。

  3) 可視化方案中要體現每個人的職業或部門屬性(五類):director,CEO,Business Development Unit,Business Support Unit,Business Control Unit。

2.1.2. 設計思路

  根據可視化要求,分析某個公司的郵件社交網絡,並可視化該郵件社交網絡。

  1. 可視化效果應該是一張圖;

  2. 這張圖中的頂點要分為5類,體現每個人的職業或部門屬性;

  3. 這張圖中的邊要分為7類,體現不同的權值;

  4. 每類頂點放在一起,並將不同頂點用不同顏色標識。

2.2. 對可視化方案的說明

  在此次的設計方案中,將使用弦圖進行可視化。弦圖的各弧代表各個人,弧的角度大小代表其收件箱內的郵件個數,弧被分為5種顏色,體現每個人的部門屬性。弦圖的各弦代表兩個人之間的郵件往來,如A、B間的弦,與A相連的一端代表A收件箱中來自B的郵件,與B相連的一端代表B收件箱中來自A的郵件,弦被分為7種寬度,體現來往信件的多少。

2.3. 使用D3實現可視化效果的過程

2.3.1. 新建項目

  在項目目錄下新建文件夾lab_3,再在文件夾lab_3內新建一個文件夾d3和文本文件index.html

2.3.2. 數據預處理

  將原始數據保存為staff.csv和mails.csv

2.3.3. 編寫代碼

html.index

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <title>My lab 3</title>
    <style>

        @import url(../style.css?aea6f0a);

        #circle circle {
            fill: none;
            pointer-events: all;
        }

        .group path {
            fill-opacity: .5;
        }

        path.chord {
            stroke: #000;
            stroke-width: .25px;
        }

        #circle:hover path.fade {
            display: none;
        }

        .Director {
            fill: navy;
        }

        .CEO {
            fill: black;
        }

        #group3, #group6, #group7, #group8 {
            fill: #00FF7F;
        }
        #group4, #group9, #group10, #group11, #group12, #group13, #group14 {
            fill: #DAA520;
        }
        #group5, #group16, #group17, #group15 {
            fill: #FF00FF;
        }
    </style>
</head>

<body>
    <script src="d3/d3.js" charset="utf-8"></script>
    <script src="d3/queue.js"></script>
    <script>
        var matrix = new Array(18);
              
        var width = 720,
            height = 720,
            outerRadius = Math.min(width, height) / 2 - 10,
            innerRadius = outerRadius - 24;   // 設置布局的長寬,半徑

        var formatPercent = d3.format(".1%");

        var layout = d3.layout.chord()    // 從關系矩陣生成一個弦圖,創建弦圖布局,用來轉換數據
            .padding(.04)     // 取得或設置 弦片段間的角填充
            .sortSubgroups(d3.descending)     // 取得或設置 用於子分組的比較器
            .sortChords(d3.ascending);    // 取得或設置 用於弦的比較器(Z軸順序)

        var arc = d3.svg.arc()      // 新建一個弧度生成器,用來畫弧
            .innerRadius(innerRadius)     // 設置內半徑訪問器
            .outerRadius(outerRadius);    // 設置外半徑訪問器

        var path = d3.svg.chord()     // 新建一個弦生成器,用來畫弦
            .radius(innerRadius);

        var svg = d3.select("body").append("svg")     // 生成最父節點
            .attr("width", width)
            .attr("height", height)
          .append("g")
            .attr("id", "circle")
            .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");    // 坐標原點移到svg中間

        svg.append("circle")
            .attr("r", outerRadius);    // 畫外圈的大圓,g的第一個孩子

        queue()
            .defer(d3.csv, "staff.csv")
            .defer(d3.csv, "mails.csv")
            .await(ready);    // 加載兩個文件,之后執行回掉函數ready
        
        function ready(error, staffs, mails) {
              if (error) throw error;

              // 生成數據矩陣
              for (var i = 0; i < 18; i++)
              {
                      matrix[i] = new Array(18);
                      for (var j = 0; j < 18; j++)
                      {
                          matrix[i][j] = 0;
                      }
              }

              for (var i = 0; i < mails.length; i++)
              {
                       var toid1 = parseInt(mails[i].toID);
                      var id2 = parseInt(mails[i].ID);
                      var num = parseInt(mails[i].Weight);
                      matrix[toid1][id2] = num;
              }
              // Compute the chord layout. 加載數據矩陣
              layout.matrix(matrix);
              
              // Add a group per neighborhood. 就是每一個扇環形區域,都是一個group,包括title、path(arc)、text三個孩子
              var group = svg.selectAll(".group")
                  .data(layout.groups)    // layout = d3.layout.chord() ,所以layout是個chord;
                                          // chord.group()返回節點數組,用來生成節點:一個個弧
                .enter().append("g")
                  .attr("class", "group")
                  .on("mouseover", mouseover);    // 放上鼠標后調用mouseover函數
              
              
              // Add a mouseover title. 鼠標停留顯示的提示
              group.append("title").text(function(d, i) { return staffs[i].Name + "'s inbox"; });

              // Add the group arc. 畫弧
              var groupPath = group.append("path")
                  .attr("id", function(d, i) { return "group" + i; })   // 每個扇環形區域是一個group,其中的path叫group i
                  .attr("d", arc)
                  .attr("class", function(d, i) { return staffs[i].Position; });


              // Add a text label. 添加文本標識
              var groupText = group.append("text")
                  .attr("x", 6)
                  .attr("dy", 15);

              groupText.append("textPath")
                  .attr("xlink:href", function(d, i) { return "#group" + i; })
                  .text( function(d, i) { return staffs[i].Name; } );

              // Remove the labels that don't fit. :(
              groupText.filter(function(d, i) { return groupPath[0][i].getTotalLength() / 2 - 16 < this.getComputedTextLength(); })
                  .remove();


              // Add the chords. 每條連接兩個鄰居的邊都是一個path,擁有一個title孩子,所有的邊在一起叫chord
              var chord = svg.selectAll(".chord")
                  .data(layout.chords)
                .enter().append("path")
                  .attr("class", "chord")
                  .style("fill", "#1E90FF")
                  .attr("d", path);

              // Add an elaborate mouseover title for each chord. 設置path的title
              // chord.append("title").text("haha");

              // 在此函數中,所有不是source也不是target的全都設"fade"為true
              function mouseover(d, i) {
                chord.classed("fade", function(p) {
                  return p.source.index != i
                      && p.target.index != i;
                });
              }
        }
    </script>
</body>
</html>

數據:mails.csv

ID,Emailspermonth,Weight,toID
0,5,1,1
0,6,1,2
1,5,1,2
2,25,2,3
2,36,2,4
2,53,3,5
3,150,4,6
3,213,5,7
3,298,5,8
4,345,6,9
4,123,4,10
4,212,5,11
4,453,7,12
4,156,4,13
4,278,5,14
5,300,5,15
5,78,3,16
5,256,5,17
6,78,3,7
6,145,4,8
7,139,4,8
9,34,2,10
9,134,4,11
9,546,7,12
9,23,2,13
9,145,4,14
10,256,5,11
10,222,5,12
10,190,4,12
10,56,3,14
11,78,3,12
11,112,4,13
12,98,3,14
15,88,3,16
15,123,4,17
16,238,5,17
17,5,1,7
16,15,2,6
16,23,2,7
16,54,3,8
16,18,2,9
16,23,2,11
16,41,2,13
16,13,2,14
16,27,2,10

數據:staff.csv

ID,Name,Position
0,James,Director
1,David,Director
2,George,CEO
3,Ronald,Business Development Manager
4,John,Business Support Manager
5,Richard,Business Control Manager
6,Daniel,Sales Department Leader
7,Kenneth,Product Department Leader
8,Anthony,Marketing Department Leader
9,Robert,Project Office Leader
10,Charles,Professional Service Leader
11,Paul,QA Leader
12,Mark,Design Office Leader
13,Kevin,Technical Support Office Leader
14,Edward,Software Development Leader
15,Joseph,Legal Office Leader
16,Michael,Finance Office Leader
17,Jason,HR Office Leader

 

3. 結果

                                                圖1   數據弦圖

                           圖2   鼠標移到某員工,顯示該員工所有的郵件往來

4. 總結

   使用弦圖能清晰地顯示各部門、各員工之間的郵件往來,有良好的可視化效果。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM