【问题标题】:DC.js line graph configurationDC.js 折线图配置
【发布时间】:2024-12-05 03:20:01
【问题描述】:

我正在尝试创建一个折线图,显示一天中特定时间的平均人数。我还想格式化 x 轴以反映和读取午夜、上午 8 点、中午、下午 5 点、晚上 8 点和晚上 11 点。由于某种原因,我的图表一直显示为空白,并且我的坐标轴从晚上 7 点开始。任何帮助表示赞赏。

我已经部分回答了我自己的问题,可以使用以下方法获取数据计数:

ok, I have partially answered my own question. To get the count, I needed to change the following:
  var volumeByHour = crossfilterData.dimension(function(d) { 
        return d.datetime ? (d.datetime.getHours()):null;

});

var volumeByHourGroup = volumeByHour.group();

这给了我访问者的原始数量,我需要平均值....

数据是这样的

[
   {
      "id":1,
      "sex":0,
      "age":65,
      "income":201428,
      "ethnicity":0,
      "datetime":"2009-04-26T00:00:00.000Z"
   },
   {
      "id":2,
      "sex":0,
      "age":75,
      "income":22851,
      "ethnicity":1,
      "datetime":"2009-04-26T01:00:00.000Z"
   },
   {
      "id":3,
      "sex":1,
      "age":27,
      "income":15672,
      "ethnicity":2,
      "datetime":"2009-04-26T02:00:00.000Z"
   },
   {
      "id":4,
      "sex":1,
      "age":69,
      "income":60719,
      "ethnicity":3,
      "datetime":"2009-04-26T03:00:00.000Z"
   },
   {
      "id":5,
      "sex":1,
      "age":18,
      "income":217262,
      "ethnicity":4,
      "datetime":"2009-04-26T04:00:00.000Z"
   },
   {
      "id":6,
      "sex":1,
      "age":76,
      "income":73308,
      "ethnicity":5,
      "datetime":"2009-04-26T05:00:00.000Z"
   },
   {
      "id":7,
      "sex":0,
      "age":51,
      "income":259663,
      "ethnicity":6,
      "datetime":"2009-04-26T06:00:00.000Z"
   },
   {
      "id":8,
      "sex":1,
      "age":42,
      "income":271168,
      "ethnicity":7,
      "datetime":"2009-04-26T07:00:00.000Z"
   },
   {
      "id":9,
      "sex":0,
      "age":42,
      "income":318753,
      "ethnicity":8,
      "datetime":"2009-04-26T08:00:00.000Z"
   },
   {
      "id":10,
      "sex":1,
      "age":94,
      "income":302247,
      "ethnicity":9,
      "datetime":"2009-04-26T09:00:00.000Z"
   },
   {
      "id":11,
      "sex":1,
      "age":94,
      "income":221124,
      "ethnicity":10,
      "datetime":"2009-04-26T10:00:00.000Z"
   },
   {
      "id":12,
      "sex":1,
      "age":56,
      "income":311643,
      "ethnicity":11,
      "datetime":"2009-04-26T11:00:00.000Z"
   },
   {
      "id":13,
      "sex":1,
      "age":79,
      "income":204746,
      "ethnicity":12,
      "datetime":"2009-04-26T12:00:00.000Z"
   },
   {
      "id":14,
      "sex":1,
      "age":54,
      "income":2451,
      "ethnicity":13,
      "datetime":"2009-04-26T13:00:00.000Z"
   },
   {
      "id":15,
      "sex":1,
      "age":100,
      "income":25213,
      "ethnicity":14,
      "datetime":"2009-04-26T14:00:00.000Z"
   },
   {
      "id":16,
      "sex":1,
      "age":71,
      "income":299937,
      "ethnicity":15,
      "datetime":"2009-04-26T15:00:00.000Z"
   },
   {
      "id":17,
      "sex":0,
      "age":91,
      "income":217957,
      "ethnicity":16,
      "datetime":"2009-04-26T16:00:00.000Z"
   },
   {
      "id":18,
      "sex":1,
      "age":98,
      "income":157079,
      "ethnicity":17,
      "datetime":"2009-04-26T17:00:00.000Z"
   },
   {
      "id":19,
      "sex":0,
      "age":57,
      "income":60152,
      "ethnicity":0,
      "datetime":"2009-04-26T18:00:00.000Z"
   },
   {
      "id":20,
      "sex":1,
      "age":94,
      "income":148961,
      "ethnicity":1,
      "datetime":"2009-04-26T19:00:00.000Z"
   },
   {
      "id":21,
      "sex":1,
      "age":29,
      "income":40591,
      "ethnicity":1,
      "datetime":"2009-04-26T20:00:00.000Z"
   }
]

并且正在像这样被加载和解析:

/*createCrossfilter() - constructs a new crossfilter
 *  @data: our data returned by the loadData callback
 */
function createCrossfilter(data, callback) {
    crossfilterData = crossfilter(data);
    crossfilterDataAll = crossfilterData.groupAll();
    if (callback !== undefined) {
        callback();
    }
}

/* loadData() - loads our dataset. a callback with our data when our data is ready to  be used.
 *  @pathToData: path to the dataset on the file system.
 */
function loadData(pathToData) {
    d3.json(pathToData, function (data) {
        globalData = data;

        // parse JSON Strings - convert to real javascript objects
        data.forEach(function (e) {
            var parseDateTime = d3.time.format("%Y-%m%dT%I:%M:%S.%LZ");
                    e.datetime = parseDateTime.parse(e.datetime);
                e.hour = d3.time.hour(e.datetime);
                e.day = d3.time.day(e.datetime);
                e.month = d3.time.month(e.datetime);
            });

我的代码如下所示:

function createTimeOfDayChart() {
// define an anchor point for the createTimeOfDayChart
charts.timeOfDayChart = dc.lineChart("#dc-timeofday-chart");

// create any dimensions
var volumeByHour = crossfilterData.dimension(function(d) { 
            return d.datetime ? (d.datetime.getHours()):null;
});

// number of visitors per hour Chart
var volumeByHourGroup = volumeByHour.group().reduceCount(function(d) {  
            return d.datetime ? (d.datetime.getHours()):null;
  });

var timeExtent = d3.extent(globalData, function(d){

    return d.hour;
});


charts.timeOfDayChart
            .width(350)
            .height(225)
            .margins({ top: 0, left: 35, right: 45, bottom: 40 }) 
            .transitionDuration(500) 
            .dimension(volumeByHour) 
            .group(volumeByHourGroup)
          //.group(crossfilterData.groupAll()) 
            .valueAccessor(function(d){
                return d.value.avg;
            })
            .elasticY(true)
            .elasticX(true)
            .x(d3.time.scale().domain(timeExtent.map(function(d) { return new Date(d);        }))
            .round(d3.time.hour.round)
            .xUnits(d3.time.hours)
            .renderHorizontalGridLines(true)
            .renderVerticalGridLines(true)
            .renderLabel(true)
            .renderArea(false)
            .brushOn(true)
            .renderLabel(true)
            .dotRadius(10)

            .renderlet(function(chart){
                var colors =d3.scale.ordinal().domain(timeExtent)
                    .range(["steelblue", "brown", "red", "green", "yellow", "grey"]);
                chart.selectAll('path.line').each(function(d){
                     d3.select(this).attr("style", "fill: " + colors(d.key)); 
                });
            })
            .xAxis().ticks(6);

【问题讨论】:

  • 我注意到您使用的是 dc 图表,我不熟悉该库,但如果您想在 d3 中指定刻度值,您可以使用 axis.tickValues。您可能必须编辑 dc 的源代码才能实现此目的,或者使用 d3 对折线图进行编码。
  • 是的,我现在正在尝试自定义它。我希望 y 轴读取 5%、10%、15%、20%、25%、30% 并尝试使线段具有不同的颜色,就像在 dimple.js 图表中一样 here 它被证明是非常挑战!!

标签: javascript d3.js dc.js


【解决方案1】:

根据 cmets 更新

首先,您需要根据一天中的时间创建维度(如上所述):

 var volumeByHour = crossfilterData.dimension(function (d) {
        return d.datetime ? (d.datetime.getHours()):null;
    });

接下来,您需要创建一个自定义 reduce 方法来跟踪每小时的总访问量和平均访问量。我使用最小和最大日期之间的差异作为平均值的股息。

    var volumeByHourGroup = volumeByHour.group().reduce(
        function (p, v) {
            ++p.count;
            p.avgCount = p.count / numberOfDays;
            return p;
        },

        function (p, v) {
            --p.count;
            p.avgCount = p.count / numberOfDays;
            return p;
        },

        function () {
            return {
                count: 0,
                avgCount: 0
            };
        });

最后,您可以调整图表以显示您想要的报价:

        timeOfDayChart.width(350)
        .height(225)
        .dimension(volumeByHour)
        .group(volumeByHourGroup)
        .x(d3.scale.linear().domain([0, 24]))       
        .valueAccessor(function(d){return d.value.avgCount})
        .xAxis().tickValues([7, 11, 16, 19, 22]);

您可能还想使用 tickFormatter 来更改每个刻度的显示方式。

这是一个更新的 jsfiddle:http://jsfiddle.net/djmartin_umich/G2nqh/

【讨论】:

  • 抱歉耽搁了,我还有另一个项目需要立即关注。我想要上午 8 点的访客总数的平均值。日子无关紧要。我所拥有的是这个,但它不是 function(p){ dataCountChart = dc.dataCount("#dc-data-count").dimension(crossfilterData).group(crossfilterDataAll); p.total += dataCountChart ; var avg = ++p.count/p.total; p.avg = (avg
  • 天数与平均功能有关,对吧?这是“每天”上午 8 点的平均访客人数。如果是这样,您将需要决定如何处理没有数据的日子。处理此问题的一种方法是确保数据每天都有 0 条记录,应计入平均值
  • 我更新了我提供的示例,以按小时对平均值进行分组。见上文。
  • 谢谢,太好了。我正在尝试更改 x 轴刻度的读取方式。而不是阅读 0-23,我希望他们阅读“Midnight”、“.”、“.”、“.”、“.”、“.”、“.”、“.”、“8am”、。 ",".",".","中午",".",".",".",".","5pm",".",".",".",".", ".","11pm" 我尝试过使用以下内容:
  • .tickFormat(function(d, i){ if (i === 0 ) { return "Midnight" ; } else if (i === 1) { return "." ; } else if (i === 2) { return "." ; } else if (i === 3) { return "." ; } else if (i === 4) { return "." ; } else if ( i === 5) { return "." ; } else if (i === 6) { return "." ; } etc });关于我做错了什么有什么建议吗?