2014-12-14 13 views
10

Ho riscontrato un problema con le etichette assegnate ai valori del mio grafico.c3js> Timeseries x valori non equidistanti

Il grafico è un numero temporale. Aggiungo valori usando la proprietà 'columns' di c3js.

Io uso timestamp puri (in secondi) e quindi li converto in stringhe usando label.format.

Tuttavia, questo è ciò che accade:

https://drive.google.com/file/d/0B9GDftIYQFIVb2Z3N2JfS2pzVjg/view?usp=sharing

, come si può notare lo spazio non è uniformemente distribuita, tra 18-21, 25-28 Ottobre e 1-4, 4-7 novembre solo due giorni mentre tutti gli altri hanno tre giorni tra le date.

Che cosa sta causando questo?

Mi piacerebbe avere spazi vuoti equidistanti (stesso numero di giorni).

Qui è un jfiddle con il codice: http://jsfiddle.net/ok1k6yjo/

var array_times = [1414540800, 1414627200]; 
var array_values = [67, 66.22]; 

var labelWeight = 'weight in kg'; 

var window_period = (30 * 24 * 3600); // last 30 days 

var today = Math.floor(new Date(2014,10,20,0,0,0,0).getTime()/1000); 
var timeEnd = today; 
var timeStart = today - window_period; 

var toShowTime = [1414540800, 1414627200]; 
var toShowValues = [67, 66.22]; 


var minT = Math.min.apply(null, array_times), 
    maxT = Math.max.apply(null, array_times.concat(today)); 

var minV = Math.min.apply(null, array_values), 
    maxV = Math.max.apply(null, array_values); 

function dateToString(e) { 
    var date = new Date(e * 1000); 
    return date.toDateString().substring(4); 
} 


var chart = c3.generate({ 
    bindto: '#chart', 
    data: { 
     x: 'times', 
     columns: [ 
      ['times'].concat(toShowTime), 
      [labelWeight].concat(toShowValues)], 
     labels: { 
      format: { 
       y: d3.format('.2') 
      } 
     }, 
     type: 'scatter' 
    }, 
    point: { 
     r: 6 
    }, 
    legend: { 
     show: false 
    }, 
    grid: { 
     x: { 
      show: true 
     }, 
     y: { 
      show: true 
     } 
    }, 
    axis: { 
     x: { 
      label: { 
       text: 'Time [days]' 
      }, 
      type: 'timeseries', 
      tick: { 
       fit: false, 
       //count: 29, 
       rotate: -75, 
       multiline: false, 
       format: function (e, d) { 
        return dateToString(e); 
       } 
      }, 
      height: 100 
     }, 
     y: { 
      label: { 
       text: 'Weight [kg]', 
       position: 'outer', 
       min: minV - 10, 
       max: maxV + 10 
      }, 
      tick: { 
       format: function (e, d) { 
        return parseFloat(e).toFixed(2); 
       } 
      }, 
     } 
    } 
}); 

chart.axis.range({min: {x:timeStart, y:minV-10}, max: {x:timeEnd, y:maxV+10}}); 

La lieve differenza è dovuta ad una diversa data di avvio.

Ecco un altro violino con problemi simili. http://jsfiddle.net/hfznh45w/5/

var d = (24 * 3600); // last 30 days 


//var array_times = [1414540800-8*d, 1414540800-d, 1414540800, 1414627200, 1414627200 + d, 1414627200 + 2 * d, 1414627200 + 3 * d]; 
//var array_values = [61, 60, 67, 66.22, 68, 68, 68]; 

var array_times = []; 
var array_values = []; 

for (var i = -8; i < 30; i++) { 
    array_times.push(1414540800 + (i * d)); 
    array_values.push(60 + i); 
} 

console.log(array_times); 
console.log(array_values); 

var labelWeight = 'weight in kg'; 

var window_period = (30 * 24 * 3600); // last 30 days 

var today = Math.floor(new Date(2014, 10, 20, 0, 0, 0, 0).getTime()/1000); 
var timeEnd = today; 
var timeStart = today - window_period; 


var minT = Math.min.apply(null, array_times), 
    maxT = Math.max.apply(null, array_times.concat(today)); 

var minV = Math.min.apply(null, array_values), 
    maxV = Math.max.apply(null, array_values); 

function dateToString(e) { 
    var date = new Date(e * 1000); 
    return date.toDateString().substring(4); 
} 


var chart = c3.generate({ 
    bindto: '#chart', 
    data: { 
     x: 'times', 
     columns: [ 
      ['times'].concat(array_times), [labelWeight].concat(array_values)], 
     labels: { 
      format: { 
       y: d3.format('.2') 
      } 
     }, 
     type: 'scatter' 
    }, 
    point: { 
     r: 6 
    }, 
    legend: { 
     show: false 
    }, 
    grid: { 
     x: { 
      show: true 
     }, 
     y: { 
      show: true 
     } 
    }, 
    axis: { 
     x: { 
      padding: { 
       left: 0, 
       right: 0, 
      }, 
      label: { 
       text: 'Time [days]' 
      }, 
      type: 'timeseries', 
      tick: { 
       fit: false, 
       rotate: -75, 
       multiline: false, 
       format: function (e, d) { 
        return dateToString(e); 
       } 
      }, 
      height: 100 
     }, 
     y: { 
      padding: { 
       top: 0, 
       bottom: 0 
      }, 
      label: { 
       text: 'Weight [kg]', 
       position: 'outer', 
       min: minV - 10, 
       max: maxV + 10 
      }, 
      tick: { 
       format: function (e, d) { 
        return parseFloat(e).toFixed(2); 
       } 
      } 
     } 
    } 
}); 

chart.axis.range({ 
    min: { 
     x: timeStart, 
     y: minV - 10 
    }, 
    max: { 
     x: timeEnd, 
     y: maxV + 10 
    } 
}); 

Qualsiasi indizio/correzione è più che benvenuto. Grazie!

+0

Avete bisogno di mantenere l'asse x in timeseries? Chiamare le etichette sull'asse x singolarmente sarebbe un'opzione? – JasTonAChair

+0

Se si intende mantenere una corrispondenza tra i dati tracciati e l'etichetta dell'asse x corrispondente: non ne ho bisogno e, in generale, per un timeseries, nessuno ne ha bisogno. Il comportamento di c3js per gli orari sembra un po 'strano. – 2dvisio

risposta

7

c3js consente di specificare quali segni di spunta verranno visualizzati sull'asse x.

Sotto asse/x/tick ho aggiunto questo -

values: [1413936000, 1414195200,1414454400,1414713600,1414972800,1415232000], 

ho convertito le date in tre intervalli di giorno con la epoch converter.

Here's the reference for solution.

posso solo supporre che se la griglia non corrispondono questi tre giorni zecche poi sono stati spingendo in un nuovo giorno ogni tick ennesima - da qui il problema. In alternativa, è possibile inserire gridlines manually.

Ecco il codice per l'asse x.

 x: { 
      label: { 
       text: 'Time [days]' 
      }, 
      type: 'timeseries', 
      tick: { 
       values: [1413936000, 1414195200,1414454400,1414713600,1414972800,1415232000], 
       fit: false, 
       //count: 29, 
       rotate: -75, 
       multiline: false, 
       format: function (e, d) { 
        return dateToString(e); 
       } 
      }, 
      height: 100 
     }, 
0

ho anche affrontato il problem.Here è come ho risolto.Usa l'asse x come categoria e non come timeseries, e manipola il corrispondente formato tick per apparire come se fosse time.

Ho semplificato il problema per renderlo generico.

Problemi (spaziatura irregolare):

var chart = c3.generate({ 
 
      data: { 
 
       x: 'xtime', 
 
       xFormat: '%Y-%m-%d-%H-%M-%S', 
 
       columns: [ 
 
        ['xtime', '2015-05-20-05-10-13', '2015-05-20-05-11-13', '2015-05-21-06-10-13'], 
 
        ['value', 30, 50, 20] 
 
       ] 
 
      }, 
 
      size: { 
 
       height: 300, 
 
       width: 600 
 
      }, 
 
      axis: { 
 
       x: { 
 
        type: 'timeseries', 
 
        // type: 'category', 
 
        tick: { 
 
         // format: function(x) { 
 
         //  var dateSubs = this.api.categories()[x].split('-'), 
 
         //   newDate = new Date(dateSubs[0], dateSubs[1], dateSubs[2], dateSubs[3], dateSubs[4], dateSubs[5], 0); 
 
         // 
 
         //  return newDate.toLocaleString(); 
 
         // } 
 

 
         format: '%e-%b-%Y %H:%M' 
 
        } 
 
       } 
 
      } 
 
     });
<link href="https://rawgit.com/masayuki0812/c3/master/c3.css" rel="stylesheet"/> 
 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.js"></script> 
 
    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> 
 

 
<div id="chart"></div>

Soluzione:

var chart = c3.generate({ 
 
      data: { 
 
       x: 'xtime', 
 
       xFormat: '%Y-%m-%d-%H-%M-%S', 
 
       columns: [ 
 
        ['xtime', '2015-05-20-05-10-13', '2015-05-20-05-11-13', '2015-05-21-06-10-13'], 
 
        ['value', 30, 50, 20] 
 
       ] 
 
      }, 
 
      size: { 
 
       height: 300, 
 
       width: 600 
 
      }, 
 
      axis: { 
 
       x: { 
 
        // type: 'timeseries', 
 
        type: 'category', 
 
        tick: { 
 
         format: function(x) { 
 
          var dateSubs = this.api.categories()[x].split('-'), 
 
           newDate = new Date(dateSubs[0], dateSubs[1], dateSubs[2], dateSubs[3], dateSubs[4], dateSubs[5], 0); 
 
         
 
          return newDate.toLocaleString(); 
 
         } 
 

 
         // format: '%e-%b-%Y %H:%M' 
 
        } 
 
       } 
 
      } 
 
     });
<link href="https://rawgit.com/masayuki0812/c3/master/c3.css" rel="stylesheet"/> 
 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.js"></script> 
 
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> 
 

 
<div id="chart"></div>

1

Ho provato tutte le risposte suggerito, bu nessuno mi ha dato quello che volevo. Il più vicino era la risposta di Partha, tuttavia, selezionando category come il tipo di grafico crea un padding sgradevole sulla sinistra e sulla destra del grafico.

La soluzione che ha funzionato meglio per me era escludere le etichette dal mio grafico e invece lavorare con un grafico indexed. Da lì, ho formattato manualmente ogni indice alla data corretta utilizzando la funzione format.

Ecco una versione semplificata del codice del manifesto originale:

var d = (30 * 24 * 3600); // last 30 days 

var array_times = [1414540800, 1414627200, 1414627200 + d, 1414627200 + 2 * d, 1414627200 + 3 * d, 1456528117]; 
var array_values = [67, 66.22, 68, 68, 68, 77]; 

var labelWeight = 'weight in kg'; 

var window_period = (30 * 24 * 3600); // last 30 days 


function dateToString(e) { 
    var date = new Date(e * 1000); 
    return date.toDateString().substring(4); 
} 


var chart = c3.generate({ 
    bindto: '#chart', 
    data: { 
     columns: [ 
      // Notice that I removed the datetimes from here 
      [labelWeight].concat(array_values) 
     ], 
     type: 'area' 
    }, 
    point: { 
     r: 6 
    }, 
    legend: { 
     show: false 
    }, 
    grid: { 
     x: { 
      show: true 
     }, 
     y: { 
      show: true 
     } 
    }, 
    axis: { 
     x: { 
      label: { 
       text: 'Time [days]' 
      }, 
      type: 'indexed', 
      tick: { 
       rotate: 90, 
       // I reference array_times manually here to 
       // convert the index to a user-friendly label 
       format: function (index) { 
        return dateToString(array_times[index]); 
       } 
      } 
     } 
    } 
}); 

violino di lavoro: http://jsfiddle.net/uop61zLc/1/

Problemi correlati