Как сгенерировать несколько панелей из нескольких линий в D3? - PullRequest
0 голосов
/ 22 февраля 2020

Я пытаюсь создать несколько панелей из нескольких линейных графиков в D3 с двухуровневой структурой данных.

Может кто-нибудь подсказать, как правильно создавать линейные графики. Я интуитивно пытался использовать двухуровневую структуру вложенных данных, но не могу найти, как правильно распределить строки в соответствующих панелях.

Смотрите результаты, которые я получил до сих пор: http://jtremblay.github.io/viz/example.html

Вот мой код.

var s = `condition,taxon,abundance,date
condition01,speciesA,0.31,2017-04-13
condition01,speciesA,0.54,2017-04-20
condition01,speciesB,0.21,2017-04-13
condition01,speciesB,0.60,2017-04-20
condition02,speciesA,0.31,2017-04-13
condition02,speciesA,0.48,2017-04-20
condition02,speciesB,0.19,2017-04-13
condition02,speciesB,0.61,2017-04-20
condition03,speciesA,0.13,2017-04-13
condition03,speciesA,0.11,2017-04-20
condition03,speciesB,0.04,2017-04-13
condition03,speciesB,0.11,2017-04-20
`;

var data = d3.csvParse(s);
data.forEach(function(d) { // Make every date in the csv data a javascript date object format
   var aDate = new Date(d.date);
   d.date = aDate;
});

var taxa = data.map(function (d){
    return d.taxon
});
taxa = taxa.filter(onlyUniqueArray);

var dates = data.map(function (d){
    return d.dates
});

var dataNested = d3.nest() // nest function allows to group the calculation per level of a factor
   .key(function(d) { return d.condition;})
   .key(function(d) { return d.taxon;})
   .entries(data);

console.log(dataNested);
var fillColors = ["#0000CD", "#00FF00", "#FF0000", "#808080"]

// color palette
var color = d3.scaleOrdinal()
    .domain(taxa)
    .range(fillColors);

//Margins
var margin =  { top: 20,  right: 20, bottom: 60, left: 50},
        width = 500 - margin.left - margin.right,
        height = 300 - margin.top - margin.bottom;

// Define dom and svg
var dom = d3.select("#viz");
var svg = dom.selectAll("multipleLineCharts")
   .data(dataNested)
   .enter()
   .append("div")
   .attr("class", "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 + ")")
       //.attr("fake", function(d) {console.log("d inside svg:"); console.log(d);})

// Add X axis --> it is a date format
var xScale = d3.scaleTime()
        .rangeRound([0, width])
xScale.domain(d3.extent(data, function(d) {return d.date; }));

svg
    .append("g")
    .attr("transform", "translate(0," + height + ")")
    .attr("class", "x axis")
    .call(d3.axisBottom(xScale))
    .selectAll("text")
    .style("text-anchor", "end")
    .attr("transform", "rotate(-90)")
    .attr("dx", "-0.8em")
    .attr("dy", "-0.45em")

//Add Y axis - Here because we want all panels to be on same scale, we cant use the dates from the global data structure.
var yScale = d3.scaleLinear()
    .domain([
        d3.min(data, function(d) { return d.abundance; } ),
        d3.max(data, function(d) { return d.abundance; } )
    ])
    .range([ height, 0 ]);

svg.append("g")
    .attr("class", "y axis")
    .call(d3.axisLeft(yScale).ticks(5));

//Add Z scale (colors)
var zScale = d3.scaleOrdinal()
    .range(fillColors);
zScale.domain(taxa);


// generate lines.
svg
    .append("path")
    .attr("class", "line")
    .style("stroke", function(d) { return zScale(d.key); })
    .attr("d", function(d, i){
        return d3.line()
            .x(function(d) { return xScale(d.date); })
            .y(function(d) { return yScale(d.abundance); })
            (data); //I know something else should go in there, but can't figure out what/how exactly...
    })


/* Util functions */
function onlyUniqueArray(value, index, self) {
    return self.indexOf(value) === index;
}

Я не понимаю, как эффективно обрабатывать мою структуру данных для того, что я хочу сделать ... Это мой 2x Вложенная структура данных адекватна тому, что я пытаюсь выполнить sh? Я пытался использовать одноуровневую структуру данных, но безуспешно.

1 Ответ

0 голосов
/ 23 февраля 2020

Наконец-то решил. Этот пример помог мне понять, как обрабатывать вложенные выборки: http://bl.ocks.org/stepheneb/1183998

По сути, последний блок кода был заменен следующим:

// generate lines.
var lines = svg.selectAll("lines")
    .data(function(d) { return d.values;})
    .enter()
    .append("path")
    .attr("class", "line")
    .attr("d", function(d){
        return d3.line()
            .x(function(d) { return xScale(d.date); })
            .y(function(d) { return yScale(d.abundance); })
            (d.values);
    })  
    .style("stroke", function(d) { return zScale(d.key); })

рабочий пример здесь: http://jtremblay.github.io/viz/example-fixed.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...