【问题标题】:c3js › Timeseries x values not evenly spacedc3js › 时间序列 x 值不均匀分布
【发布时间】:2015-02-12 17:11:27
【问题描述】:

我对分配给图表值的标签有疑问。

图表是一个时间序列。我使用 c3js 的“列”属性添加值。

我使用纯时间戳(以秒为单位),然后使用 label.format 将它们转换为字符串。

然而,事情是这样的:

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

您可以注意到,空间分布不均,10 月 18 日至 25 日至 28 日和 11 月 1 日至 4 日、4 日至 7 日之间只有两天,而所有其他日期之间有三天。

这是什么原因造成的?

我希望有均匀的间隔(相同的天数)。

下面是代码: 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}});

略有不同是由于开始日期不同。

这是另一个类似问题的小提琴。 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
    }
});

任何线索/修复都非常受欢迎。 谢谢!

【问题讨论】:

  • 是否需要在时间序列中保留 x 轴?可以单独命名 x 轴上的标签吗?
  • 如果你的意思是保持绘制数据和相应的 x 轴标签之间的对应关系:我不需要那个,通常,对于时间序列,不需要那个。 c3js 对于时间序列的行为似乎有点奇怪。

标签: c3.js


【解决方案1】:

c3js 允许您指定在 x 轴上出现的刻度。

在axis/x/tick下我添加了这个-

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

我使用epoch converter 以三天为间隔转换了您的日期。

Here's the reference for solution.

我只能假设如果网格线与这三天的刻度不匹配,那么它们每隔 n 个刻度就会进入新的一天 - 因此你的问题。 或者,您可以发送gridlines manually

这是 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
        },

【讨论】:

    【解决方案2】:

    将 tick.fit 设置为 false 可以使刻度根据数据点的 x 值定位。

    http://c3js.org/reference.html#axis-x-tick-fit

    axis: {
      x: {
        tick: {
          fit: true
        }
      }
    }
    

    这是来自官方网站http://c3js.org/samples/axes_x_tick_fit.html的示例

    【讨论】:

      【解决方案3】:

      我尝试了所有建议的答案,但没有一个给出我想要的答案。最接近的是 Partha 的回答,但是,选择 category 作为图表类型会在图表的左侧和右侧产生难看的填充。

      最适合我的解决方案是从我的图表中排除标签,而是使用indexed 图表。从那里,我使用 format 函数手动将每个索引格式化为正确的日期。

      这是原始海报代码的简化版本:

      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]);
                      }
                  }
              }
          }
      });
      

      工作小提琴:http://jsfiddle.net/uop61zLc/1/

      【讨论】:

        【解决方案4】:

        我也遇到了这个问题。这是我解决的方法。使用 x 轴作为类别而不是时间序列,并操作相应的刻度格式使其看起来像是时间序列。

        我已经简化了概率以使其通用。

        问题(不规则间距):

        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>

        解决方案:

        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>

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-01-22
          • 2020-10-08
          • 1970-01-01
          • 2017-01-09
          相关资源
          最近更新 更多