2015-10-13 4 views
1

У меня есть секция db sunburst, которая отлично работает с текстовыми данными непосредственно в файле .js. Теперь я хочу загрузить/прочитать и внешний файл .csv, чтобы каждый раз, когда мои данные менялись, он будет отображаться на графике.Раздел Sunburst D3 и внешний .csv

Вот мой .js файл:

// Dimensions of sunburst. 
var width = 950; 
var height = 750; 
var radius = Math.min(width, height)/2; 

// Breadcrumb dimensions: width, height, spacing, width of tip/tail. 
var b = { 
    w: 150, h: 30, s: 3, t: 10 
}; 

// Mapping of step names to colors. 
var colors = { 
    "1": "#766A62", 
    "Vehicle Downtime": "#766A62", 
    "Vehicle Downtime": "#766A62", 
    "Vehicle Downtime": "#766A62", 
    "Vehicle Downtime": "#766A62", 
    "Vehicle Downtime": "#766A62", 
    "2": "#EAAB00", 
    "4": "#8E9300", 
    "5": "#006983", 
    "TARGET MET": "#6ab975", 
    "TARGET NOT MET": "#f03e33", 
}; 

// Total size of all segments; we set this later, after loading the data. 
var totalSize = 0; 

var vis = d3.select("#chart").append("svg:svg") 
    .attr("width", width) 
    .attr("height", height) 
    .append("svg:g") 
    .attr("id", "container") 
    .attr("transform", "translate(" + width/2 + "," + height/2 + ")"); 

var partition = d3.layout.partition() 
    .size([2 * Math.PI, radius * radius]) 
    .value(function(d) { return d.size; }); 

var arc = d3.svg.arc() 
    .startAngle(function(d) { return d.x; }) 
    .endAngle(function(d) { return d.x + d.dx; }) 
    .innerRadius(function(d) { return Math.sqrt(d.y); }) 
    .outerRadius(function(d) { return Math.sqrt(d.y + d.dy); }); 

// Use d3.text and d3.csv.parseRows so that we do not need to have a header 
// row, and can receive the csv as an array of arrays. 

d3.text("mypizza.csv", function(text) { 
    var csv = d3.csv.parseRows(text); 
    var json = buildHierarchy(csv); 
    createVisualization(json); 
}); 


/*var text = 

"1-Actual spending/budget x 100-Financial Management Cost Control-TARGET NOT MET-TARGET MET-TARGET MET-TARGET MET,1\n\ 
2-Number of Health & Safety issues addressed/Number of Health & Safety issues reported-Address Health & Safety Issues-TARGET NOT MET-TARGET MET-TARGET MET-TARGET NOT MET,1\n\ 
4-Number of hours of training-Staff Training & Development-TARGET NOT MET-TARGET NOT MET-TARGET NOT MET-TARGET MET,1\n\ 
5-As per plan-Going Regional-TARGET NOT MET-TARGET NOT MET-TARGET MET-TARGET MET,1\n\ 
1-Number of days in operational-Vehicle Downtime-TARGET NOT MET-TARGET MET-TARGET MET-TARGET MET,1\n\ 
2-Budget/Time-Investing in Science & in our Future-TARGET NOT MET-TARGET MET-TARGET MET-TARGET MET,1\n\ 
4-number of staff-Staff Training & Development-TARGET NOT MET-TARGET MET-TARGET NOT MET-TARGET NOT MET,1\n\ 
5-Organise one (1) outreach programme annually-Collaboration with other government agencies-TARGET MET-TARGET NOT MET-TARGET NOT MET-TARGET MET,1\n\ 
1-Number of days in operational-Generator downtime-TARGET NOT MET-TARGET NOT MET-TARGET NOT MET-TARGET MET,1\n\ 
2-Budget variation-Investment-TARGET MET-TARGET MET-TARGET NOT MET-TARGET NOT MET,1\n\ 
4-Number of hours of training-Attract and retain staff-TARGET MET-TARGET MET-TARGET NOT MET-TARGET NOT MET,1\n\ 
1-Current projects runing at the field station-Attract Scientific Projects to Basse Field Station-TARGET MET-TARGET MET-TARGET NOT MET-TARGET NOT MET,1\n\ 
2-Organise at least one HSE awareness programme at each field station before the end of the year-Maintain staff interest in HSE-TARGET NOT MET-TARGET MET-TARGET MET-TARGET MET,1\n\ 
4-Number of hours of training-People-TARGET MET-TARGET MET-TARGET MET-TARGET MET,1\n\ 
1-Availability of electricity-Value for money-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
2-Develop occupational risks register and communicate to staff members before commencement of their duties and updated versions communicated to old staff members annually-Occupational risks management-TARGET MET-TARGET MET-TARGET MET-TARGET NOT MET,1\n\ 
4-As per HSE plan-Knowledge in HSE-TARGET NOT MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
1-Streaming IT procurement-Value for money-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
2-50% workforce participation-MRC & Me-TARGET NOT MET-TARGET NOT MET-TARGET NOT MET-TARGET MET,1\n\ 
4-90% starters complete module 1-eLearning induction-TARGET NOT MET-TARGET MET-TARGET MET-TARGET NOT MET,1\n\ 
1-Non availability of water-Value for money-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
2-No disputes-Employee relations-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
4-90% compliance-Performance Development Review-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
1-Timely completion of Work Requests-Value for money-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
2-Security audit-Information Security-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
4-As per plan-Training staff in Quality Related Matters and Enhance the concept of Quality-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
1-Budget variation-Cost Control-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
2-Train IT staff, a professional certificate per staff per year-Attract and retain staff-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
1-Have a system in place to manage waste production; and chemical use in the laboratories-Improving efficiency-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
2-As per plan-Retaining GCLP Accreditation-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
2-As per plan-Maintain applicable Quality Standards-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
1-Full implementation by January 2016-Attract & retain staff-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
2-As per audits-Improve on Applicable Quality Standards-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
1-% recovery-Value for Money-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
1-Content management and collaborating systems, implement one new productivity suite-Productivity-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
1-Monitor help desk metrics-Reliable and enabling IT platform-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
1-Install and monitor systems at identified facilities-Invest in more electronic access control Systems-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
1-Install & implement a Visitor management systems-Acquire a visitor management system-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
1-Quarterly meetings with G4S operations manager-Managing the security contract-TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
1-BCT Meetings and Drills/Exercises-Emergency Preparedness Planning – General & site specific -TARGET MET-TARGET NOT MET-TARGET MET-TARGET NOT MET,1\n\ 
"; 
*/ 

    //var csv = d3.csv.parseRows(text); 
// var json = buildHierarchy(csv); 
// createVisualization(json); 


// Main function to draw and set up the visualization, once we have the data. 
function createVisualization(json) { 

    // Basic setup of page elements. 
    initializeBreadcrumbTrail(); 
    drawLegend(); 
    d3.select("#togglelegend").on("click", toggleLegend); 

    // Bounding circle underneath the sunburst, to make it easier to detect 
    // when the mouse leaves the parent g. 
    vis.append("svg:circle") 
     .attr("r", radius) 
     .style("opacity", 0); 

    // For efficiency, filter nodes to keep only those large enough to see. 
    var nodes = partition.nodes(json) 
     .filter(function(d) { 
     return (d.dx > 0.005); // 0.005 radians = 0.29 degrees 
     }); 

    var path = vis.data([json]).selectAll("path") 
     .data(nodes) 
     .enter().append("svg:path") 
     .attr("display", function(d) { return d.depth ? null : "none"; }) 
     .attr("d", arc) 
     .attr("fill-rule", "evenodd") 
     //.style("fill", function(d) { return colors[d.name]; }) 
     .style("fill", function(d) {return d.depth==2 ? colors[d.parent.name] : colors[d.name];}) 
     //.style("fill", function(d) { if(d.depth!=2) {return colors[d.name];} else {return colors[d.parent.name];} }) 
     .style("opacity", 1) 
     .on("mouseover", mouseover); 

    // Add the mouseleave handler to the bounding circle. 
    d3.select("#container").on("mouseleave", mouseleave); 

    // Get total size of the tree = value of root node from partition. 
    totalSize = path.node().__data__.value; 
}; 

// Fade all but the current sequence, and show it in the breadcrumb trail. 
function mouseover(d) { 
    if (d.depth > 3) { 
    var mission = "MISSION: " + getAncestors(d)[0].name; 
    var kpi = "KPI: " + getAncestors(d)[1].name; 
    var goal = "GOAL: " + getAncestors(d)[2].name; 
    //console.log(kpi); 
    var yesno = ""; 
    if (d.name === "TARGET MET") { 
     yesno = "Q" + (d.depth - 3) + ": " + "Target met"; 
    } 
    else { 
     yesno = "Q" + (d.depth - 3) + ": " + "Target not met"; 
    } 
    } 
    else if (d.depth === 3) { 
    mission = "MISSION: " + getAncestors(d)[0].name; 
    kpi = "KPI: " + getAncestors(d)[1].name; 
    goal = "GOAL: " + getAncestors(d)[2].name; 
    } 
    else if (d.depth === 1) { 
    mission = "MISSION: " + d.name; 
    } 
    else { 
    //mission = Math.round((d.value/totalSize)*100)+"%"; 
    mission = "MISSION: " + getAncestors(d)[0].name; 
    mission = "ME: " + d.name; 
    //kpi = "KPI: " + getAncestors(d)[1].name; 
    //goal = "GOAL: " + getAncestors(d)[2].name; 
    } 
    var percentageString = mission + "\n" + kpi + "\n" + goal; 
    d3.select("#percentage") 
     .text(mission); 
    d3.select("#percentage2") 
     .text(goal); 
    d3.select("#percentage3") 
     .text(yesno); 
    d3.select("#percentage4") 
     .text(kpi); 

    d3.select("#explanation") 
     .style("visibility", ""); 

    var sequenceArray = getAncestors(d); 
    updateBreadcrumbs(sequenceArray, percentageString); 

    // Fade all the segments. 
    d3.selectAll("path") 
     .style("opacity", 0.3); 

    // Then highlight only those that are an ancestor of the current segment. 
    vis.selectAll("path") 
     .filter(function(node) { 
       return (sequenceArray.indexOf(node) >= 0); 
       }) 
     .style("opacity", 1); 
} 

// Restore everything to full opacity when moving off the visualization. 
function mouseleave(d) { 

    // Hide the breadcrumb trail 
    d3.select("#trail") 
     .style("visibility", "hidden"); 

    // Deactivate all segments during transition. 
    d3.selectAll("path").on("mouseover", null); 

    // Transition each segment to full opacity and then reactivate it. 
    d3.selectAll("path") 
     .transition() 
     .duration(1000) 
     .style("opacity", 1) 
     .each("end", function() { 
       d3.select(this).on("mouseover", mouseover); 
      }); 

    d3.select("#explanation") 
     .transition() 
     .duration(1000) 
     .style("visibility", "hidden"); 
} 

// Given a node in a partition layout, return an array of all of its ancestor 
// nodes, highest first, but excluding the root. 
function getAncestors(node) { 
    var path = []; 
    var current = node; 
    while (current.parent) { 
    path.unshift(current); 
    current = current.parent; 
    } 
    return path; 
} 

function initializeBreadcrumbTrail() { 
    // Add the svg area. 
    var trail = d3.select("#sequence").append("svg:svg") 
     .attr("width", width) 
     .attr("height", 50) 
     .attr("id", "trail"); 
} 

// Generate a string that describes the points of a breadcrumb polygon. 
function breadcrumbPoints(d, i) { 
    var points = []; 
    points.push("0,0"); 
    points.push(b.w + ",0"); 
    points.push(b.w + b.t + "," + (b.h/2)); 
    points.push(b.w + "," + b.h); 
    points.push("0," + b.h); 
    if (i > 0) { // Leftmost breadcrumb; don't include 6th vertex. 
    points.push(b.t + "," + (b.h/2)); 
    } 
    return points.join(" "); 
} 

// Update the breadcrumb trail to show the current sequence and percentage. 
function updateBreadcrumbs(nodeArray, percentageString) { 

    // Data join; key function combines name and depth (= position in sequence). 
    var g = d3.select("#trail") 
     .selectAll("g") 
     .data(nodeArray, function(d) { return d.name + d.depth; }); 

    // Add breadcrumb and label for entering nodes. 
    var entering = g.enter().append("svg:g"); 

    entering.append("svg:polygon") 
     .attr("points", breadcrumbPoints) 
     .style("fill", function(d) { if(d.depth!=2) {return colors[d.name];} else {return colors[d.parent.name];} }) 


    entering.append("svg:text") 
     .attr("x", (b.w + b.t)/2) 
     .attr("y", b.h/2) 
     .attr("dy", "0.35em") 
     .attr("text-anchor", "middle") 
     .text(function(d) { return d.name; }); 

    // Set position for entering and updating nodes. 
    g.attr("transform", function(d, i) { 
    return "translate(" + i * (b.w + b.s) + ", 0)"; 
    }); 

    // Remove exiting nodes. 
    g.exit().remove(); 

    // Now move and update the percentage at the end. 
    d3.select("#trail").select("#endlabel") 
     .attr("x", (nodeArray.length + 0.5) * (b.w + b.s)) 
     .attr("y", b.h/2) 
     .attr("dy", "0.35em") 
     .attr("text-anchor", "middle") 
     .text(percentageString); 

    // Make the breadcrumb trail visible, if it's hidden. 
    d3.select("#trail") 
     .style("visibility", ""); 

} 

function drawLegend() { 

    // Dimensions of legend item: width, height, spacing, radius of rounded rect. 
    var li = { 
    w: 75, h: 30, s: 3, r: 3 
    }; 

    var legend = d3.select("#legend").append("svg:svg") 
     .attr("width", li.w) 
     .attr("height", d3.keys(colors).length * (li.h + li.s)); 

    var g = legend.selectAll("g") 
     .data(d3.entries(colors)) 
     .enter().append("svg:g") 
     .attr("transform", function(d, i) { 
       return "translate(0," + i * (li.h + li.s) + ")"; 
      }); 

    g.append("svg:rect") 
     .attr("rx", li.r) 
     .attr("ry", li.r) 
     .attr("width", li.w) 
     .attr("height", li.h) 
     .style("fill", function(d) { return d.value; }); 

    g.append("svg:text") 
     .attr("x", li.w/2) 
     .attr("y", li.h/2) 
     .attr("dy", "0.35em") 
     .attr("text-anchor", "middle") 
     .text(function(d) { return d.key; }); 
} 
function toggleLegend() { 
    var legend = d3.select("#legend"); 
    if (legend.style("visibility") == "hidden") { 
    legend.style("visibility", ""); 
    } else { 
    legend.style("visibility", "hidden"); 
    } 
} 
// Take a 2-column CSV and transform it into a hierarchical structure suitable 
// for a partition layout. The first column is a sequence of step names, from 
// root to leaf, separated by hyphens. The second column is a count of how 
// often that sequence occurred. 
function buildHierarchy(csv) { 
    var root = {"name": "root", "children": []}; 
    for (var i = 0; i < csv.length; i++) { 
    var sequence = csv[i][0]; 
    var size = +csv[i][1]; 
    if (isNaN(size)) { // e.g. if this is a header row 
     continue; 
    } 
    var parts = sequence.split("-"); 
    var currentNode = root; 
    for (var j = 0; j < parts.length; j++) { 
     var children = currentNode["children"]; 
     var nodeName = parts[j]; 
     var childNode; 
     if (j + 1 < parts.length) { 
    // Not yet at the end of the sequence; move down the tree. 
    var foundChild = false; 
    for (var k = 0; k < children.length; k++) { 
     if (children[k]["name"] == nodeName) { 
     childNode = children[k]; 
     foundChild = true; 
     break; 
     } 
    } 
    // If we don't already have a child node for this branch, create it. 
    if (!foundChild) { 
     childNode = {"name": nodeName, "children": []}; 
     children.push(childNode); 
    } 
    currentNode = childNode; 
     } else { 
    // Reached the end of the sequence; create a leaf node. 
    childNode = {"name": nodeName, "size": size}; 
    children.push(childNode); 
     } 
    } 
    } 
    return root; 
}; 

Как вы можете видеть исходный текст комментировал работает отлично. Но загрузка внешнего файла mypizza.csv, который имеет такую ​​же структуру, не работает.

Вот эта ссылка для mypizza.csv.

Я так новичок в этом, и я надеюсь, что кто-то там может помочь мне сделать это.

Благодаря

FP

+0

Мне кажется, что что-то с текстом/csv выключено. Цитированная переменная 'text' использует разделитель (-) как разделитель, тогда как у вас есть запятые в csv. Таким образом, в функции 'buildHierarchy' вы можете использовать неправильные индексы (или разделять на тире и т. Д.). Я думаю, вы могли бы проверить, что ... –

+0

Привет, я пробовал почти все ваши предложения и другие, но я не уверен, что они продвигаются вперед. Может ли кто-нибудь еще помочь с этим? –

ответ

0

Как и в моем комментарии выше, я настроил функцию buildHierarchy следующим образом:

function buildHierarchy(csv) { 
    var root = { 
     "name": "root", 
      "children": [] 
    }; 
    for (var i = 0; i < csv.length; i++) { 
     var sequence = csv[i]; //[0]; 
     var size = +csv[i][0]; 

     if (isNaN(size)) { // e.g. if this is a header row 
      continue; 
     } 
     var parts = sequence; //.split("-"); 
etc.... 

Как вы можете видеть, в вашем коде вы не должны разделить больше, поскольку значения, которые входят в функцию, уже разделены. Поэтому я также скорректировал sequence и size vars на соответствующие значения (возможно, неправильные, но это работает, для примера).

В вашем случае size всегда в NaN был, поэтому не так много происходит

Вы можете поиграться со значениями и привести все в порядок так, как вам это нужно.

Вы можете найти результат здесь: Fiddle

ПРИМЕЧАНИЕ: Я просто поправил код для отображения Sunburst, но у меня не было времени, чтобы установить все вверх (сухари и т.д.). Я уверен, что ты найдешь свой путь!

Удачи.

+0

Это потрясающе. Работает как очарование, и я уже наслаждаюсь этим. У меня есть несколько способов сделать, но в целом код работает. Благодарю. –

+0

Cool - спасибо за отзыв! –

+0

Мне удалось собрать все вместе для вашей ценной помощи @Pinguin. Тем не менее, теперь я имею дело с проблемами, связанными с IE, по крайней мере, с версией 9. Я не тестировал более поздние версии. Вот ссылка на окончательный [link] (http://www.mrc.gm/KPI). Мои индикаторы в Q1, Q2 ... не отображаются, как ожидалось. Когда вы наводите курсор на каждый цвет красного или зеленого цвета, он должен указывать на цели справа. Это отлично работает в других браузерах, но не IE 9 по крайней мере. –