2015-04-15 6 views
0

Я пытаюсь сделать визуальное представление файла, который я извлекаю как csv. Но я, кажется, ударяю о стену со структурой, которую ожидает d3 Tree.d3.js Дерево - атрибуты CSV для узлов

Мой код:

<script src="http://d3js.org/d3.v3.min.js"></script> 
<script src="mydata.csv"></script> 
<script> 
    var margin = {top: 20, right: 120, bottom: 20, left: 120}, 
    width = 800 - margin.right - margin.left, 
    height = 500 - margin.top - margin.bottom; 

    var canvas = d3.select("body").append("svg") 
    .attr("width", 2000) 
    .attr("height", height + margin.top + margin.bottom) 
    .append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

    var tree = d3.layout.tree() 
    .size([height, width]); 

    var diagonal = d3.svg.diagonal() 
    .projection(function(d) { return [d.y, d.x]; }); 

d3.csv("mydata.csv", function(data) { 

    var nested_data = d3.nest() 
     .key(function(d) { return d['Machine']; }) 
     .key(function(d) { return d['Name']; }) 
     .entries(data); 

    flare_data.key = "Flare"; 
    flare_data.values = nested_data; 
    flare_data = reSortFlare(flare_data); //Turns Key Values into Name Children which D3 Tree expects 

    var nodes = tree.nodes(flare_data); 

    var link = canvas.selectAll(".link") 
    .data(tree.links(nodes)) 
    .enter().append("path") 
    .attr("class", "link") 
    .attr("d", diagonal); 

    var node = canvas.selectAll(".node") 
    .data(nodes) 
    .enter() 
    .append("g") 
     .attr("class", "node") 
     .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; }); 

    node.append("circle") 
    .attr("r", 7); 

    node.append("text") 
    .attr("dx", function(d) { return d.children ? -15 : 15; }) 
    .attr("dy", 3) 
    .style("text-anchor", function(d) { return d.children ? "end" : "start"; }) 
.text(function(d) { return d.children ? d.name : [d['URL Template'], d['xPath']]; }); 
    }); 

    function reSortFlare(root) { 
    //console.log("Calling"); 
    for (var key in root) { 
     if (key == "key") { 
     root.name = root.key; 
     delete root.key; 
     } 
     if (key == "values") { 
     root.children = []; 
     for (item in root.values) { 
      root.children.push(reSortFlare(root.values[item])); 
     } 
     delete root.values; 
     } 
    } 
    return root; 
    } 
</script> 

Мой CSV файл Пример:

Machine,Name,URL Template,Page Start,Page Size,Max 
Pages,xPath,RegEx,eCommerce,Search Interval,Additional Variable,Variable Value 
"Machine [1]","eSearch - Web-GB","http://example.com/status","1","1","10","//somethingness","([0-9]{1,20})","1","0","Thum","true" 
"Machine [1]","eSearch - Web-GB","http://forexample.com/randomness","1","1","10","//nothingness","([0-9]{1,20})","1","0","Kapool","true" 
"Machine [1]","Web: Web-US","http://mangasite.com/mangacomic","1","1","10","//itemId","([0-9]{1,20})","1","0","Crawl Natural URL","true" 
"Machine [1]","Web: Web-US","http://someothersite.fr/kapala","1","1","10","//itemId","([0-9]{1,20})","1","0","Block Sellers","true" 
"Machine [1]","Link Test","http://kistergans.com/papals","0","1","1","//a/@href","(.*)","0","0",, 
"Machine [1]","TW Search","https://mankini.jp/ofcourse","0","100","1","//a/@href","(.*/status/.*)","0","0",, 
"Machine [1]","TW API","http://storagewars.com","0","1","1","//a/@href","(http.*)","0","0",, 
"Machine [1]","Amiz Metaquery","http://www.Amiz.com/s/","1","10","1","//a[contains]/@href","(http://www\.Amiz\.com/","0","0",, 
"Machine [1]","Amiz Metaquery Too","http://www.Amiz.de/s/?field-keywords=%q&page=%i","1","1","10","//div/@href","http://www.Amiz.de/).*","0","0",, 
"Machine [2]","Subs.com","https://www.subs.com/search?f=%q&p=%i","0","1","10","//dt/a/@href","((https?://[^/]+)?/[^/\+]{10,500})","0","0",, 
"Machine [2]","Extra.cc","http://extra.cc/search/","1","1","10","//a/@href","([^#]+)","0","0",, 
"Machine [2]","Monitoring","http://monitoring.com/nothing","1","1","1","//nothing","(.*)","0","0",, 
"Machine [2]","SM - abe.com - users","http://s.weibo.com/user/lamborghini","1","1","1","//div[@class=""person_detail""]/p[@class=""person_addr""]/a/@href","(.*)","0","0",, 
"Machine [2]","SM - koko.com","http://i.youku.com/u_search/?page=%i&q=%q","1","1","10","//li[@class=""u_title""]/a/@href","(http://i.youku.com/u/.+)","0","0",, 
"Machine [2]","Amiz.com Page","http://www.Amiz.com/s/?field-keywords=%q&page=%i","1","1","5","//div[@id=""rightResultsATF""]//@href","/dp/([^/]+)/.*","1","0",, 
"Machine [3]","MA: Apple.com (iTunes)","http://software.com/aabc","0","200","1","//iTunesApp/trackViewUrl","(@keli)","1","0",, 
"Machine [3]","MA: Wipple.com","http://kalamaza.ck/keywords","0","48","5","//a/@href","(http://abc.ck)","0","0",, 
"Machine [3]","SM: Linkage.com ","http://stormborn.com/lalala","0","100","5","//a/@href","(lililo+)","0","0",, 
"Machine [3]","SM: Afro.com - via SearchTool","http://lipidi.li/lili","0","1","1","//a/@href","(.*/status/[0-9]+)","0","0",, 
"Machine [3]","SM: Afro.com","http://sazdarma.ka/yoyo","0","1","1","//a/@href","(.*/status/[0-9]+)","0","0",, 

Это создает дерево, которое выглядит примерно так D3 Tree CSV

Моя проблема заключается в том, что мне нужно ребенка каждой машины (например, «eSearch - Web-GB»), чтобы иметь отдельный узел (имя, шаблон URL, начало страницы, размер страницы, максимальные страницы и т. д.). Но с атрибутом text, хотя я могу вернуть все эти атрибуты, все они возвращаются вместе с разделителем запятой, а не как отдельные узлы.

Я загрузил код в JSFiddle, но, похоже, он не работает.

Любая помощь будет оценена по достоинству.

Кроме того, есть ли более простой способ преобразования CSV в соответствующий формат JSON?

+0

создали JSFiddle и мы можем иметь посмотрите, куда вы идете неправильно :) –

+0

Добавлен в JSFiddle – ZeW

+0

ничего не отображается на вашей скрипке? –

ответ

1

Во-первых, вам не нужна ваша reSortFlare функцию. Это можно сделать, изменив значение children accessor function.

var tree = d3.layout.tree() 
    .size([height, width]) 
    .children(function(d){ 
     return d.values; 
    }); 

Во-вторых, я полагаю, вы можете делать то, что вам нужно с .rollup:

var nested_data = d3.nest() 
    .key(function(d) { 
     return d['Machine']; 
    }) 
    .key(function(d) { 
     return d['Name']; 
    }) 
    .rollup(function(d){ 
     var children = []; 
     d.forEach(function(dSub){ 
     for (var k in dSub){ 
       if (k == 'URL Template' || k == 'xPath') 
        children.push({'key': dSub[k]}) 
      } 
     }) 
     return children; 
    }) 
    .entries(data); 

Это дает (пример code here):

enter image description here

+0

Спасибо, много, это заняло у меня столько времени, и это было так просто :) – ZeW

+0

Жаль, что я мог бы удвоить голос. – ZeW

0

var pre_data = d3.csv.parse(d3.select("pre#data").text()); 
 

 
//document.getElementsByTagName("BODY")[0].innerHTML = data; 
 

 
var margin = { 
 
    top: 20, 
 
    right: 120, 
 
    bottom: 20, 
 
    left: 120 
 
}, 
 
width = 1000 - margin.right - margin.left, 
 
    height = 500 - margin.top - margin.bottom; 
 

 
var canvas = d3.select("body").append("svg") 
 
    .attr("width", 2000) 
 
    .attr("height", height + margin.top + margin.bottom) 
 
    .append("g") 
 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 
 

 
var tree = d3.layout.tree() 
 
    .size([height, width]); 
 

 
var diagonal = d3.svg.diagonal() 
 
    .projection(function (d) { 
 
    return [d.y, d.x]; 
 
}); 
 

 
var div = d3.select("body").append("div") 
 
    .attr("class", "tooltip") 
 
    .style("opacity", 0); 
 

 

 
    //var nested_data = _.nest(csv_data, "Machine"); 
 
    //var nodes = tree.nodes(nested_data); 
 
    var flare_data = {}; 
 
    var nested_data = d3.nest() 
 
     .key(function (d) { 
 
     return d['Machine']; 
 
    }) 
 
     .key(function (d) { 
 
     return d['Name']; 
 
    }) 
 
     .entries(pre_data); 
 
    flare_data.key = "Flare"; 
 
    flare_data.values = nested_data; 
 
    flare_data = reSortFlare(flare_data); 
 
    var nodes = tree.nodes(flare_data); 
 

 

 

 
    var link = canvas.selectAll(".link") 
 
     .data(tree.links(nodes)) 
 
     .enter().append("path") 
 
     .attr("class", "link") 
 
     .attr("d", diagonal); 
 

 
    var node = canvas.selectAll(".node") 
 
     .data(nodes) 
 
     .enter() 
 
     .append("g") 
 
     .attr("class", "node") 
 
     .attr("transform", function (d) { 
 
     return "translate(" + d.y + "," + d.x + ")"; 
 
    }); 
 

 
    node.append("circle") 
 
     .attr("r", 7) 
 
     .on("mouseover", function (d) { 
 
     div.transition() 
 
      .duration(200) 
 
      .style("opacity", .9); 
 
     div.html(
 
      "Name: " + (d.name?d.name:d["URL Template"]+(d.xPath.replace("//","/"))) + "<br/>" + 
 
      "URL Template: " + d['URL Template'] + "<br/>" + 
 
      "Page Start: " + d['Page Start'] + "<br/>" + 
 
      "Page Size: " + d['Page Size'] + "<br/>" + 
 
      "Max Pages: " + d['Max Pages'] + "<br/>" + 
 
      "xPath:&nbsp" + d['xPath'] + "<br/>" + 
 
      "RegEx: " + d['RegEx'] + "<br/>" + 
 
      "eCommerce: " + d['eCommerce'] + "<br/>" + 
 
      "Search Interval: " + d['Search Interval'] + "<br/>" + 
 
      "Additional Variable: " + d['Additional Variable'] + "<br/>" + 
 
      "Variable Value: " + d['Variable Value'] + "<br/>") 
 
      .style("left", (d3.event.pageX) + "px") 
 
      .style("top", (d3.event.pageY - 28) + "px"); 
 
    }) 
 
     .on("click", function (d) { 
 
     div.transition() 
 
      .duration(500) 
 
      .style("opacity", 0); 
 
    }); 
 

 
    node.append("text") 
 
     .attr("dx", function (d) { 
 
     return d.children ? -15 : 15; 
 
    }) 
 
     .attr("dy", 3) 
 
     .style("text-anchor", function (d) { 
 
     return d.children ? "end" : "start"; 
 
    }) 
 
     .text(function (d) { 
 
     //return d.children ? d.name : d['Name']; 
 
     return d.children ? d.name : d["URL Template"]+(d.xPath.replace("//","/")); 
 
    }); 
 

 

 
function reSortFlare(d) { 
 
    //console.log("Calling"); 
 
    for (var key in d) { 
 
     if (key == "key") { 
 
      d.name = d.key; 
 
      delete d.key; 
 
     } 
 
     if (key == "values") { 
 
      d.children = []; 
 
      for (var item in d.values) { 
 
       d.children.push(reSortFlare(d.values[item])); 
 
      } 
 
      delete d.values; 
 
     } 
 
    } 
 
    return d; 
 
}
.node circle { 
 
     fill: #fff; 
 
     stroke: #4B9FC3; 
 
     stroke-width: 3px; 
 
    } 
 
    .node { 
 
     font: 12px sans-serif; 
 
    } 
 
    .link { 
 
     fill: none; 
 
     stroke: #ccc; 
 
     stroke-width: 2x; 
 
    } 
 
    div.tooltip { 
 
     position: absolute; 
 
     text-align: left; 
 
     width: 500px; 
 
     height: 200px; 
 
     padding: 2px; 
 
     font: 12px sans-serif; 
 
     background: lightsteelblue; 
 
     border: 0px; 
 
     border-radius: 8px; 
 
     pointer-events: none; 
 
    } 
 
    pre { 
 
     display:none; 
 
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 
<body> 
 
    <pre id="data">Machine,Name,URL Template,Page Start,Page Size,Max Pages,xPath,RegEx,eCommerce,Search Interval,Additional Variable,Variable Value 
 
"Machine [1]","eSearch - Web-GB","http://example.com/status","1","1","10","//somethingness","([0-9]{1,20})","1","0","Thum","true" 
 
"Machine [1]","eSearch - Web-GB","http://forexample.com/randomness","1","1","10","//nothingness","([0-9]{1,20})","1","0","Kapool","true" 
 
"Machine [1]","Web: Web-US","http://mangasite.com/mangacomic","1","1","10","//itemId","([0-9]{1,20})","1","0","Crawl Natural URL","true" 
 
"Machine [1]","Web: Web-US","http://someothersite.fr/kapala","1","1","10","//itemId","([0-9]{1,20})","1","0","Block Sellers","true" 
 
"Machine [1]","Link Test","http://kistergans.com/papals","0","1","1","//a/@href","(.*)","0","0",, 
 
"Machine [1]","TW Search","https://mankini.jp/ofcourse","0","100","1","//a/@href","(.*/status/.*)","0","0",, 
 
"Machine [1]","TW API","http://storagewars.com","0","1","1","//a/@href","(http.*)","0","0",, 
 
"Machine [1]","Amiz Metaquery","http://www.Amiz.com/s/","1","10","1","//a[contains]/@href","(http://www\.Amiz\.com/","0","0",, 
 
"Machine [1]","Amiz Metaquery Too","http://www.Amiz.de/s/?field-keywords=%q&page=%i","1","1","10","//div/@href","http://www.Amiz.de/).*","0","0",, 
 
"Machine [2]","Subs.com","https://www.subs.com/search?f=%q&p=%i","0","1","10","//dt/a/@href","((https?://[^/]+)?/[^/\+]{10,500})","0","0",, 
 
"Machine [2]","Extra.cc","http://extra.cc/search/","1","1","10","//a/@href","([^#]+)","0","0",, 
 
"Machine [2]","Monitoring","http://monitoring.com/nothing","1","1","1","//nothing","(.*)","0","0",, 
 
"Machine [2]","SM - abe.com - users","http://s.weibo.com/user/lamborghini","1","1","1","//div[@class=""person_detail""]/p[@class=""person_addr""]/a/@href","(.*)","0","0",, 
 
"Machine [2]","SM - koko.com","http://i.youku.com/u_search/?page=%i&q=%q","1","1","10","//li[@class=""u_title""]/a/@href","(http://i.youku.com/u/.+)","0","0",, 
 
"Machine [2]","Amiz.com Page","http://www.Amiz.com/s/?field-keywords=%q&page=%i","1","1","5","//div[@id=""rightResultsATF""]//@href","/dp/([^/]+)/.*","1","0",, 
 
"Machine [3]","MA: Apple.com (iTunes)","http://software.com/aabc","0","200","1","//iTunesApp/trackViewUrl","(@keli)","1","0",, 
 
"Machine [3]","MA: Wipple.com","http://kalamaza.ck/keywords","0","48","5","//a/@href","(http://abc.ck)","0","0",, 
 
"Machine [3]","SM: Linkage.com ","http://stormborn.com/lalala","0","100","5","//a/@href","(lililo+)","0","0",, 
 
"Machine [3]","SM: Afro.com - via SearchTool","http://lipidi.li/lili","0","1","1","//a/@href","(.*/status/[0-9]+)","0","0",, 
 
"Machine [3]","SM: Afro.com","http://sazdarma.ka/yoyo","0","1","1","//a/@href","(.*/status/[0-9]+)","0","0",,</pre> 
 
</body>

Я думаю, что вы ищете это, если не спрашивайте меня больше ...

+0

Привет, спасибо за помощь. Что делает ваша модификация, это URL-адрес URL-адреса и xPath один за другим в тексте. Мне нужно указать URL-адрес шаблона, xPath и все остальные в качестве дочерних элементов каждого (eSearch-Web-GB) типа родителя. Как и всплывающая подсказка, они перечислены как дети. – ZeW

Смежные вопросы