He logrado que esta visualización (pequeños múltiplos de gráficos de área apilados) funcione, en una forma ligeramente diferente, cuando uso datos ficticios para las fechas, es decir, cuando uso solo años. Sin embargo, cuando uso fechas reales como esta, es problemático:

Record,Code,2008-1-1,2008-2-1,2008-3-1,2008-4-1,2008-5-1,2008-6-1,2008-7-1...

En lugar de estos datos ficticios, que funcionan bien

Record,Code,1895,1896,1897,1898,1899,1900,1901...

Cuando uso fechas completas, el navegador se cuelga; No hay ningún mensaje de error. He corregido errores de análisis antes, pero este parece estar más allá de mis habilidades.

Aquí está el Plunker que no funciona: https://plnkr.co/edit/fOlpxo648OyCSM7Sq8ak?p=preview Otro Plunker, uno que realmente carga, pero que usa datos ficticios, está al final de esta pregunta.

Este código parece particularmente problemático:

function createDatesArr(start, end) {
var arr = [];
for (var i = start; i <= end; i++ ) {
    arr.push((i));  //      arr.push(String(i));
}
return arr;
}

En una forma ligeramente diferente, recibiré un mensaje de error que indica que "fechas" no se han definido. Intenté resolver esto con el siguiente código:

var dateFormat = d3.time.format("%Y-%m-%d");
var startDate = new Date('2008-1-1');
var endDate = new Date ('2017-12-1');
var dates = createDatesArr(startDate, endDate); 

O así:

var dateFormat = d3.time.format("%Y-%m-%d");
var startYear = "2008-1-1";
var endYear = "2017-12-1";
var dates = createYearsArr(startYear, endYear);

O así:

var dateFormat = d3.time.format("%Y-%m-%d");
var startDate = d3.min(dataset, function(d) { return d.Date; });
var endDate = d3.max(dataset, function(d) { return d.Date; });
var dates = createDatesArr(startDate, endDate);

O, alternativamente, definiendo "fechas" así:

d3.csv(dataPath, function(data) {
    var dates = d3.keys(data[0]).slice(1);
    data = data.filter(function(d) {
            return true;
    });
    var dates = d3.keys(data[0]).slice(1);

Nada de esto ha funcionado, pero espero que alguien pueda ayudarme a solucionarlo.

Aquí hay otro Plunker, que realmente funciona, que demuestra lo que finalmente estoy tratando de lograr, aunque usando datos ficticios (solo años) para fechas: http://plnkr.co/edit/jRC8iQg2kdtlZWtGE020?p=preview

Por favor, ayúdeme.

4
LaissezPasser 28 oct. 2017 a las 07:18

3 respuestas

La mejor respuesta

Tienes razón, tu problema en este código

function createDatesArr(start, end) {
  var arr = [];
  for (var i = start; i <= end; i++ ) {
    arr.push((i));  //      arr.push(String(i));
  }
  return arr;
}

Más precisamente aquí: i++;

Mire la imagen a continuación, variable i es una fecha en milisegundos. Lo aumenta en un milisegundo después de cada iteración de bucle. Pero paso entre sus puntos de datos, ya que puedo ver que es un mes.

Record,Code,2008-1-1,2008-2-1,2008-3-1,2008-4-1,2008-5-1,2008-6-1,2008-7-1...

enter image description here

Por lo tanto, debe aumentar i en un mes después de cada iteración de bucle para resolver su problema.

Puede hacerlo con d3.time.month.offset :

for (var i = start; i <= end; i = d3.time.month.offset(i, 1)) {
  arr.push((i));
}

Después de eso, debe eliminar dateFormat(...) porque el elemento de datos es una fecha de JavaScript exactamente válida y reescribe un poco la función transformData, mire mi fork of you plnkr (parece una aplicación incorrecta de colores, creo que puede solucionarlo, pero de lo contrario funciona).

4
Mikhail Shabrikov 28 oct. 2017 a las 07:56

Primero de todo en este fragmento:

function createDatesArr(start, end) {
 var arr = [];
  for (var i = start; i <= end; i++ ) {
    arr.push((i));  //      arr.push(String(i));
  }
  return arr;
}

El uso de i ++ no funcionará, ya que está tratando de usar la operación postfix no en una expresión válida. No puedes saltar los días usando esto:

( Fri Dec 01 2017 00:00:00 GMT+0400 (+04) ) ++

Si está tratando de obtener todos los meses en diapason, puede usar este simple fragmento a continuación:

   function createDatesArr(startDate, endDate) {
       var _start = new Date(startDate),
           _end = new Date(endDate),
           _result = [];

       while(_start < _end){
           _result.push(_start);
           // going next
           var _newDate = _start.setDate(_start.getDate() + 1);
               _start = new Date(_newDate);
       }
       return _result;
    }
2
Levon Grigoryan 28 oct. 2017 a las 06:37

Solo para proporcionar información adicional a esta pregunta, que ya tiene dos buenas respuestas: no necesita esa horrenda función createDatesArr (que fue la causa de sus problemas aquí).

Puede obtener fácilmente una matriz de fechas entre una fecha de inicio y una fecha de finalización con una escala de tiempo, utilizando time.ticks([interval]), que:

Devuelve fechas representativas del dominio de la escala. Los valores de tick devueltos están uniformemente espaciados (en su mayoría), tienen valores sensibles (como todos los días a medianoche) y se garantiza que están dentro del alcance del dominio.

No solo eso es más seguro que su función, sino que también es idiomático D3, lo que significa que su propósito es fácilmente entendido por otros programadores de D3.

Aquí hay una demostración usando v3, que es su versión. Cambié la fecha de finalización a 2009 en lugar de 2017, por lo que tendremos menos fechas en la consola. Revisalo:

var startDate = new Date('2008-1-1');
var endDate = new Date('2009-6-1');
var dates = d3.time.scale()
  .domain([startDate, endDate])
  .ticks(d3.time.months, 1);

console.log(dates)
<script src="https://d3js.org/d3.v3.min.js"></script>

En realidad, esto puede ser aún más corto, solo una línea, bajando la escala de tiempo y usando solo d3.time.months o d3.time.month.range:

var dates = d3.time.month.range(new Date('2008-1-1'), new Date('2009-6-1'), 1)

console.log(dates)
<script src="https://d3js.org/d3.v3.min.js"></script>
2
Gerardo Furtado 28 oct. 2017 a las 12:06