2015-12-28 4 views
2

У меня есть данные для первой и следующей попытки в поисках убежища в Германии для беженцев и, следовательно, два графика, которые ищут, как этотИдей для отчетливой слоистости сложенных графа в D3.js

Первого один First attempt/arrivals

Второй один enter image description here

Переход от одного к другому shoulnd't быть проблемой я полагаю, но то, что я хочу показать, так как из них в одном графике тоже. Таким образом, комбинация обоих наборов данных для каждой страны. Но можно ли отличить друг от друга, если я объединим страны и первый и следующий («erst/folge»)? Каждая страна должна иметь на слое, разделенном на две, одна - первая попытка, вторая - вторая попытка этой страны. Одной идеей отличия этих подслоев является, может быть, обычная колоссальная область, которую я сейчас пытаюсь попробовать. Как показать оба данных на одном графике? Возможно ли даже присоединиться к обоим наборам данных и по-прежнему видеть разницу?

Вот мой HTML:

<!DOCTYPE html> 
 
<meta charset="utf-8"> 
 
<style> 
 

 
body { 
 
    font: 10px sans-serif; 
 
} 
 

 
.chart { 
 
    background: #fff; 
 
} 
 

 
p { 
 
    font: 12px helvetica; 
 
} 
 

 

 
.axis path, .axis line { 
 
    fill: none; 
 
    stroke: #000; 
 
    stroke-width: 2px; 
 
    shape-rendering: crispEdges; 
 
} 
 

 
button { 
 
    position: absolute; 
 
    right: 50px; 
 
    top: 10px; 
 
} 
 

 
</style> 
 
<body> 
 
<script src="http://d3js.org/d3.v2.js"></script> 
 
<div id="option"> 
 
    <input name="updateButton" 
 
      type="button" 
 
      value="Show Data for second Attemp" 
 
      onclick="updateSecond('folgeantraege_monatlich_2015_mitentscheidungenbisnovember.csv')" /> 
 

 
</div> 
 

 
<div id="option"> 
 
    <input name="updateButton" 
 
      type="button" 
 
      value="Show Data for first Attemp" 
 
      onclick="updateFirst('erstantraege_monatlich_2015_mitentscheidungenbisnovember.csv')" /> 
 

 
</div> 
 

 
<div id="option"> 
 
    <input name="updateButton" 
 
      type="button" 
 
      value="Show both" 
 
      onclick="updateBoth('erstantraege_monatlich_2015_mitentscheidungenbisnovember.csv', 'folgeantraege_monatlich_2015_mitentscheidungenbisnovember.csv')" /> 
 

 
</div> 
 

 
<div class="chart"> 
 
</div> 
 

 
<script> 
 

 
var margin = {top: 20, right: 40, bottom: 30, left: 30}; 
 
var width = document.body.clientWidth - margin.left - margin.right; 
 
var height = 400 - margin.top - margin.bottom; 
 

 
var x = d3.time.scale() 
 
    .range([0, width]); 
 

 
var y = d3.scale.linear() 
 
    .range([height-10, 0]); 
 
var dateParser = d3.time.format("%Y-%m-%d").parse; 
 

 
var stack = d3.layout.stack() 
 
    .offset("zero") 
 
    .values(function(d) { return d.values; }) 
 
    .x(function(d) { return d.date; }) 
 
    .y(function(d) { return d.value; }); 
 

 
var area = d3.svg.area() 
 
    .interpolate("cardinal") 
 
    .x(function(d) { return x(d.date); }) 
 
    .y0(function(d) { return y(d.y0); }) 
 
    .y1(function(d) { return y(d.y0 + d.y); }); 
 
var z = d3.scale.category20() 
 

 
chart("erstantraege_monatlich_2015_mitentscheidungenbisnovember.csv"); 
 

 
var datearray = []; 
 
var colorrange = []; 
 

 
function chart(csvpath) { 
 

 
// var dateParser = d3.time.format("%Y-%m-%d").parse; 
 
// var margin = {top: 20, right: 40, bottom: 30, left: 30}; 
 
// var width = document.body.clientWidth - margin.left - margin.right; 
 
// var height = 400 - margin.top - margin.bottom; 
 

 
// var x = d3.time.scale() 
 
//  .range([0, width]); 
 
// 
 
// var y = d3.scale.linear() 
 
//  .range([height-10, 0]); 
 

 
// var z = d3.scale.category20() 
 

 
//var color = d3.scale.category10() 
 

 
var xAxis = d3.svg.axis() 
 
    .scale(x) 
 
    .orient("bottom") 
 
    .ticks(d3.time.months); 
 

 
var yAxis = d3.svg.axis() 
 
    .scale(y); 
 

 
var yAxisr = d3.svg.axis() 
 
    .scale(y); 
 

 
// var stack = d3.layout.stack() 
 
//  .offset("zero") 
 
//  .values(function(d) { return d.values; }) 
 
//  .x(function(d) { return d.date; }) 
 
//  .y(function(d) { return d.value; }); 
 

 
var nest = d3.nest() 
 
    .key(function(d) { return d.Land}); 
 
// var nestFiltered = nest.filter(function(d){ 
 
//  return d.Land != 'Total'; 
 
// }) 
 

 
// var area = d3.svg.area() 
 
//  .interpolate("cardinal") 
 
//  .x(function(d) { return x(d.date); }) 
 
//  .y0(function(d) { return y(d.y0); }) 
 
//  .y1(function(d) { return y(d.y0 + d.y); }); 
 

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

 
    d3.csv(csvpath, function(data) { 
 
    data.forEach(function(d) { 
 
     d.date = dateParser(d.Datum); 
 
     d.value = +d.ErstanträgeZahl; 
 
    }); 
 

 
\t //onsole.log(data); 
 
    var layers = stack(nest.entries(data)); 
 
    console.log(nest.entries(data)); 
 

 
    x.domain(d3.extent(data, function(d) { return d.date; })); 
 
    y.domain([0, d3.max(data, function(d) { return d.y0 + d.y; })]); 
 

 
    svg.selectAll(".layer") 
 
     .data(layers) 
 
     .enter().append("path") 
 
     .attr("class", "layer") 
 
     .attr("d", function(d) { return area(d.values); }) 
 
     .style("fill", function(d, i) { return z(i); }); 
 

 

 

 
    svg.append("g") 
 
     .attr("class", "x axis") 
 
     .attr("transform", "translate(0," + height + ")") 
 
     .call(xAxis); 
 

 
    svg.append("g") 
 
     .attr("class", "y axis") 
 
     .attr("transform", "translate(" + width + ", 0)") 
 
     .call(yAxis.orient("right")); 
 

 
    svg.append("g") 
 
     .attr("class", "y axis") 
 
     .call(yAxis.orient("left")); 
 

 
}); 
 
} 
 

 
function updateSecond(csvpath) { 
 
    var nest = d3.nest() 
 
     .key(function(d) { return d.Land}); 
 

 
    d3.csv(csvpath, function(data) { 
 
    data.forEach(function(d) { 
 
     d.date = dateParser(d.Datum); 
 
     d.value = +d.Summe; 
 
     console.log(d.date); 
 
     console.log(d.value); 
 
    }); 
 
    var layers = stack(nest.entries(data)); 
 

 
    x.domain(d3.extent(data, function(d) { return d.date; })); 
 
    y.domain([0, d3.max(data, function(d) { return d.y0 + d.y; })]); 
 
    d3.selectAll("path") 
 
     .data(layers) 
 
     .transition() 
 
     .duration(750) 
 
     .style("fill", function(d, i) { return z(i); }) 
 
     .attr("d", function(d) { return area(d.values); }); 
 
    svg.select(".y.axis") // change the y axis 
 
     .duration(750) 
 
     .call(yAxis); 
 

 

 
    }); 
 

 

 

 

 
} 
 

 
function updateFirst(csvpath) { 
 
    var nest = d3.nest() 
 
     .key(function(d) { return d.Land}); 
 

 
    d3.csv(csvpath, function(data) { 
 
    data.forEach(function(d) { 
 
     d.date = dateParser(d.Datum); 
 
     d.value = +d.ErstanträgeZahl; 
 
     console.log(d.date); 
 
     console.log(d.value); 
 
    }); 
 
    var layers = stack(nest.entries(data)); 
 

 
    x.domain(d3.extent(data, function(d) { return d.date; })); 
 
    y.domain([0, d3.max(data, function(d) { return d.y0 + d.y; })]); 
 
    d3.selectAll("path") 
 
     .data(layers) 
 
     .transition() 
 
     .duration(750) 
 
     .style("fill", function(d, i) { return z(i); }) 
 
     .attr("d", function(d) { return area(d.values); }); 
 
    svg.select(".y.axis") // change the y axis 
 
     .duration(750) 
 
     .call(yAxis); 
 

 

 

 
    }); 
 
} 
 
function updateBoth(csvpathFirst, csvpathSecond){ 
 
    var nest = d3.nest() 
 
     .key(function(d) { return d.Land}); 
 

 
    d3.csv(csvpathFirst, function(data1) { 
 
    d3.csv(csvpathSecond, function(data2) { 
 
     
 
    }); 
 

 
    }); 
 

 

 
} 
 
</script>

И мои данные здесь в моем repo

EDIT1: Например csv1 содержит

Datum,Land,Summe,Position,Antragsart,EntscheidungenInsgesamt,Asylberechtigt,Flüchtling,GewährungVonSubsidiäremSchutz,Abschiebungsverbot,UnbegrenzteAblehnungen,Ablehnung,sonstigeVerfahrenserledigungen 
2015-01-01,Afghanistan,1129,5,Erst,418,0,105,4,58,66,6,179 
2015-02-01,Afghanistan,969,5,Erst,849,9,186,16,100,131,10,397 
2015-03-01,Afghanistan,885,5,Erst,1376,17,309,58,158,201,11,622 
2015-04-01,Afghanistan,1119,6,Erst,1838,21,384,75,202,261,15,880 
2015-05-01,Afghanistan,1151,6,Erst,2272,21,499,91,249,303,16,1093 
2015-06-01,Afghanistan,2051,6,Erst,2911,23,683,132,313,377,19,1364 
2015-07-01,Afghanistan,2104,6,Erst,3340,27,767,160,366,431,21,1568 
2015-08-01,Afghanistan,2270,5,Erst,3660,28,922,172,409,453,23,1653 
2015-09-01,Afghanistan,2724,4,Erst,4057,36,1049,201,455,475,26,1815 
2015-10-01,Afghanistan,3770,4,Erst,4540,37,1188,234,516,538,29,1998 
2015-11-01,Afghanistan,4929,0,Erst,5026,46,1340,253,620,623,49,2095 

d csv2 содержит

Datum,Antragsart,Land,Summe,Position,Datum2,Position,Herkunft,Entscheidungeninsgesamt,Asylberechtigt,Prozent,Flüchtling,Pronzent,GewährungvonsubisdiäremSchutz,Prozent,Abschiebungsverbot,Prozent,UnbegrenzteAblehnungen,Prozent,Ablehnung,Prozent,keinweiteresverfahren,Prozent,sonstigeVerfahrenserledigungen,Prozent 
2015-01-01,Folge,Afghanistan,33,10,2015-01-01,10,Afghanistan,29,0,0,5,17.2,2,6.9,8,27.6,0,0,0,0,1,3.4,13,44.8 
2015-02-01,Folge,Afghanistan,29,10,2015-02-01,10,Afghanistan,81,0,0,13,16,4,4.9,22,27.2,0,0,0,0,10,12.3,32,39.5 
2015-03-01,Folge,Afghanistan,41,9,2015-03-01,9,Afghanistan,135,0,0,21,15.6,10,7.4,37,27.4,1,0.7,0,0,23,17,43,31.9 
2015-04-01,Folge,Afghanistan,25,10,2015-04-01,10,Afghanistan,165,0,0,34,20.6,12,7.3,41,24.8,4,2.4,0,0,30,18.2,44,26.7 
2015-05-01,Folge,Afghanistan,37,9,2015-05-01,9,Afghanistan,212,0,0,54,25.5,12,5.7,50,23.6,4,1.9,0,0,32,15.1,60,28.3 
2015-06-01,Folge,Afghanistan,35,9,2015-06-01,9,Afghanistan,261,0,0,72,27.6,17,6.5,59,22.6,6,2.3,0,0,35,13.4,72,27.6 
2015-07-01,Folge,Afghanistan,35,9,2015-07-01,9,Afghanistan,288,0,0,82,28.5,17,5.9,64,22.2,6,2.1,0,0,42,14.6,77,26.7 
2015-08-01,Folge,Afghanistan,34,9,2015-08-01,9,Afghanistan,321,0,0,100,31.2,20,6.2,66,20.6,6,1.9,0,0,52,16.2,77,24 
2015-09-01,Folge,Afghanistan,27,4,2015-09-01,9,Afghanistan,354,0,0,120,33.9,20,5.6,72,20.3,7,2,0,0,54,15.3,81,22.9 
2015-10-01,Folge,Afghanistan,24,9,2015-10-01,9,Afghanistan,389,0,0,136,35,20,5.1,83,21.3,7,1.8,0,0,54,13.9,89,22.9 
2015-11-01,Folge,Afghanistan,47,,,,,431,1,0.2,148,34.3,23,5.3,97,22.5,8,1.9,0,0,58,13.5,96,22.3 

Значения («Самму») необходимо просуммировать значения в месяц каждой страны (Афганистан), но и должен отражать ценности для их стек самой по себе (Прямо сейчас я пытаюсь выяснить, как использовать texture.js и custom scales использовать текстуры, чтобы отличать цвета от другого, потому что каждая страна должна иметь собственный цвет на этом графике, но, как я уже упоминал, они должны быть разными в своих подслоях. Scribble Когда я пытаюсь поставить оба csv fiels в одном файле я получаю не совсем, но что-то похожее на это Fail1enter image description here Можете ли вы дать мне несколько советов, как архивировать подслои (данные структура/алгоритм или что я предпринимаю для достижения этого), поэтому я могу продолжить и попытаться реализовать текстуры?

Заранее спасибо

Final EDIT в ответ Кириллов:

var margin = {top: 20, right: 40, bottom: 30, left: 30}; 
var width = document.body.clientWidth - margin.left - margin.right; 
var height = 400 - margin.top - margin.bottom; 

var x = d3.time.scale() 
    .range([0, width]); 

var y = d3.scale.linear() 
    .range([height-10, 0]); 
var dateParser = d3.time.format("%Y-%m-%d").parse; 

var stack = d3.layout.stack() 
    .offset("zero") 
    .values(function(d) { return d.values; }) 
    .x(function(d) { return d.graphDate; }) 
    .y(function(d) { return d.value; }); 

var area = d3.svg.area() 
    .interpolate("cardinal") 
    .x(function(d) { return x(d.graphDate); }) 
    .y0(function(d) { return y(d.y0); }) 
    .y1(function(d) { return y(d.y0 + d.y); }); 
var z = d3.scale.category20() 

doInit(); 
updateFirst('data/all.csv'); 

function doInit(){ 
    //make the svg and axis 
    xAxis = d3.svg.axis() 
    .scale(x) 
    .orient("bottom") 
    .ticks(d3.time.months); 

    yAxis = d3.svg.axis() 
     .scale(y); 

    yAxisr = d3.svg.axis() 
     .scale(y); 
    //make svg 
    var graph = d3.select(".chart").append("svg") 
    .attr("width", width + margin.left + margin.right) 
    .attr("height", height + margin.top + margin.bottom) 
    .append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

    graph.append("g") 
     .attr("class", "x axis") 
     .attr("transform", "translate(0," + height + ")") 
     .call(xAxis); 

    graph.append("g") 
     .attr("class", "y axis yright") 
     .attr("transform", "translate(" + width + ", 0)") 
     .call(yAxis.orient("right")); 

    graph.append("g") 
     .attr("class", "y axis yleft") 

     .call(yAxis.orient("left")); 
} 

function updateFirst(csvpath) { 
    var nest = d3.nest() 
     .key(function(d) { return d.Land+ "-" + d.Antragsart}); 
    //console.log(nest); 

    d3.csv(csvpath, function(data) { 
    data.forEach(function(d) { 
     //console.log(data); 
     d.graphDate = dateParser(d.Datum); 
     d.value = +d.Summe; 
     d.type= d.Antragsart; 
    }); 

    var layers = stack(nest.entries(data)).sort(function(a,b){return d3.ascending(a.key, b.key)}); 
    console.log(layers); 
    x.domain(d3.extent(data, function(d) { return d.graphDate; })); 
    y.domain([0, d3.max(data, function(d) { return d.y0 + d.y; })]); 
    var k = d3.select("g .x") 
     .call(xAxis); 


    d3.select("g .yright") 
     .call(yAxis); 
    d3.select("g .yleft") 
     .call(yAxis); 
    d3.selectAll("defs").remove(); 
    d3.select(".chart svg g").selectAll("path").remove(); 

    d3.select(".chart svg g").selectAll("path") 
     .data(layers).enter().append("path") 
     //.style("fill", function(d, i) { console.log(d.key);return z(d.key); }) 
     .attr("class", function(d){ 
      var country = d.key.split("-")[0]; 
      var src = d.key.split("-")[1]; 
      return src; 
     }) 
     .style("fill", function(d){ 
      var country = d.key.split("-")[0]; 
      var src = d.key.split("-")[1]; 
      if (src === "Folge"){ 
      var t = textures.lines().thicker(2).stroke(z(country)); 
      d3.select(".chart").select("svg").call(t); 
      return t.url(); 
      } else { 
      return z(country); 
      } 
     }) 
     .attr("d", function(d) { return area(d.values); }); 
    }); 
} 
+1

Проверьте это Джейсон Дэвис [статья] (https://www.jasondavies.com/american-forces-in-afghanistan-and-iraq/). Похоже на то, что вы хотите, он использует бары, но не графы области. – Mark

+0

Я посмотрю на это. спасибо – basedian

+0

У меня есть проблемы, чтобы применить общую идею примера к моей версии. Хотя у них есть сходство, я застреваю. Можете ли вы дать мне больше советов/информации? Например, я не знаю, что делать с переменной области в streamgraph и как я обрабатываю преобразование генной переменной. – basedian

ответ

1

Для объединения записей я пользуясь d3 queue..Read here

Целью этого является загрузите 2 CSV через ajax и когда оба загружены, вызывает обратный вызов.

queue() 
    .defer(d3.csv, csvpathFirst) //using queue so that callback is called after loading both CSVs 
    .defer(d3.csv, csvpathSecond) 
    .await(makeMyChart); 

    function makeMyChart(error, first, second) { 
    var data = []; 

сделать вложенную функцию в зависимости от страны и CSV

вар гнездо = ​​d3.nest() .key (функция (г) { возвратного d.Land + "-" + d.src ; // d.src является первым, если сначала csv второй, если наоборот });

Следующая я сливаясь записи, как это:

//iterate first 
first.forEach(function(d) { 
    d.graphDate = dateParser(d.Datum); 
    d.value = +d.Summe; 
    d.src = "first" 
    data.push(d) 
}); 
//iterate second 
second.forEach(function(d) { 
    d.graphDate = dateParser(d.Datum); 
    d.value = +d.Summe; 
    d.src = "second" 
    data.push(d) 
}); 
//sort layers on basis of country 
var layers = stack(nest.entries(data)).sort(function(a, b) { 
    return d3.ascending(a.key, b.key) 
}); 

Регенерация ось, как это:

//regenerate the axis with new domains 
var k = d3.select("g .x") 
    .call(xAxis); 
d3.select("g .yright") 
    .call(yAxis); 
d3.select("g .yleft") 
    .call(yAxis); 

Удалить все старые пути и defs DOM так:

d3.selectAll("defs").remove(); 
d3.select(".chart svg g").selectAll("path").remove(); 

Далее в зависимости от страны и первого CSV и второго CSV добавить стиль заполнения.

.style("fill", function(d) { 
    var country = d.key.split("-")[0]; 
    var src = d.key.split("-")[1]; 
    if (src === "first") { 
     //use texture.js for pattern 
     var t = textures.lines().thicker().stroke(z(country)); 
     d3.select(".chart").select("svg").call(t); 
     return t.url(); 
    } else { 
     return z(country); 
    } 
    }) 

Рабочий код here

Надеется, что это помогает!

+0

Большое огромное спасибо вашим усилиям. Я получаю представление о вашем коде. Одна маленькая вещь, которую я пытаюсь обойти, состоит в том, что данные первого и второго действительно складываются на основе их цвета, а затем текстуры, но я думаю, что это невозможно в зависимости от характера потока, который я просто не могу сложить страны (цвет, затем текстура, следующая страна, затем текстура и т. д.) – basedian

+0

Да, вы правы, что не можете иметь альтернативные страны .. это зависит от набора данных. – Cyril

+0

Итак, когда я объединяю даты, возможно, у меня могут быть альтернативные наборы данных? У меня есть запись, в которой говорится, если она первая или вторая. – basedian

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