对相同日期的值求和

问题描述 投票:0回答:3

我想在D3.js中绘制图表。它是Date VS值图。但是,当Date相同时,我的几个值不同。我想考虑Date相似的值的总和。这是数据的样子,

[

    {
        Date : "2017-12-15",
        Sales : "50"

    },
    {   Date : "2017-12-16",
        Sales : "20"

    },
    {
        Date : "2017-12-17",
        Sales : "30"
    },
    {
        Date : "2017-12-18",
        Sales : "10"
    },
    {
        Date : "2017-12-18",
        Sales : "40"
    },
    {
        Date : "2017-12-19",
        Sales : "60"
    }


]

你可以看到,在2017-12-18上有两个Sales值,1040。我想考虑(10 + 40)2017-12-18的总和(每当有相同的Sales时有不同的Date值)。

JS: -

var data = [

    {
        Date : "2017-12-15",
        Sales : "50"

    },
    {   Date : "2017-12-16",
        Sales : "20"

    },
    {
        Date : "2017-12-17",
        Sales : "30"
    },
    {
        Date : "2017-12-18",
        Sales : "10"
    },
    {
        Date : "2017-12-18",
        Sales : "40"
    },
    {
        Date : "2017-12-19",
        Sales : "60"
    }


].map(function(entry) {
  return {
    Date: d3.timeParse("%Y-%m-%d")(entry.Date),
    Sales: +entry.Sales
  }
});

var svg = d3.select("svg"),
    margin = {top: 20, right: 20, bottom: 30, left: 50},
    width = +svg.attr("width") - margin.left - margin.right,
    height = +svg.attr("height") - margin.top - margin.bottom,
    g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var x = d3.scaleTime()
    .rangeRound([0, width]);

var y = d3.scaleLinear()
    .rangeRound([height, 0]);

var line = d3.line()
    .x(function(d) { return x(d.Date); })
    .y(function(d) { return y(d.Sales); });

x.domain(d3.extent(data, function(d) { return d.Date; }));
y.domain(d3.extent(data, function(d) { return d.Sales; }));

g.append("g")
    .attr("transform", "translate(0," + height + ")")
    .call(d3.axisBottom(x))

g.append("g")
    .call(d3.axisLeft(y))

g.append("path")
    .datum(data)
    .attr("fill", "none")
    .attr("stroke", "steelblue")
    .attr("stroke-linejoin", "round")
    .attr("stroke-linecap", "round")
    .attr("stroke-width", 1.5)
    .attr("d", line);

HTML: -

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.12.0/d3.min.js"></script>

<svg width="600" height="180"></svg>

这里发生的是,只有当Date相同时才取较高的值,而不取和值。

javascript d3.js
3个回答
0
投票

有几种方法可以对该数组中的对象求和。也许,JavaScript中最惯用的方式是使用reduce

var data = [{
  Date: "2017-12-15",
  Sales: "50"
}, {
  Date: "2017-12-16",
  Sales: "20"
}, {
  Date: "2017-12-17",
  Sales: "30"
}, {
  Date: "2017-12-18",
  Sales: "10"
}, {
  Date: "2017-12-18",
  Sales: "40"
}, {
  Date: "2017-12-19",
  Sales: "60"
}];

var reduced = data.reduce(function(allDates, date) {
  if (allDates.some(function(e) {
      return e.Date === date.Date
    })) {
    allDates.filter(function(e) {
      return e.Date === date.Date
    })[0].Sales += +date.Sales
  } else {
    allDates.push({
      Date: date.Date,
      Sales: +date.Sales
    })
  }
  return allDates
}, []);

console.log(reduced)

之后,只需要创建一个基本的SVG路径:

var rawData = [

  {
    Date: "2017-12-15",
    Sales: "50"

  }, {
    Date: "2017-12-16",
    Sales: "20"

  }, {
    Date: "2017-12-17",
    Sales: "30"
  }, {
    Date: "2017-12-18",
    Sales: "10"
  }, {
    Date: "2017-12-18",
    Sales: "40"
  }, {
    Date: "2017-12-19",
    Sales: "60"
  }


];

var data = rawData.reduce(function(allDates, date) {
  if (allDates.some(function(e) {
      return e.Date === date.Date
    })) {
    allDates.filter(function(e) {
      return e.Date === date.Date
    })[0].Sales += +date.Sales
  } else {
    allDates.push({
      Date: date.Date,
      Sales: +date.Sales
    })
  }
  return allDates
}, []);

data.forEach(function(d) {
  d.Date = d3.timeParse("%Y-%m-%d")(d.Date)
})

var svg = d3.select("svg"),
  margin = {
    top: 20,
    right: 20,
    bottom: 30,
    left: 50
  },
  width = +svg.attr("width") - margin.left - margin.right,
  height = +svg.attr("height") - margin.top - margin.bottom,
  g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var x = d3.scaleTime()
  .rangeRound([0, width]);

var y = d3.scaleLinear()
  .rangeRound([height, 0]);

var line = d3.line()
  .x(function(d) {
    return x(d.Date);
  })
  .y(function(d) {
    return y(d.Sales);
  });

x.domain(d3.extent(data, function(d) {
  return d.Date;
}));
y.domain(d3.extent(data, function(d) {
  return d.Sales;
}));

g.append("g")
  .attr("transform", "translate(0," + height + ")")
  .call(d3.axisBottom(x))

g.append("g")
  .call(d3.axisLeft(y))

g.append("path")
  .datum(data)
  .attr("fill", "none")
  .attr("stroke", "steelblue")
  .attr("stroke-linejoin", "round")
  .attr("stroke-linecap", "round")
  .attr("stroke-width", 1.5)
  .attr("d", line);
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="600" height="180"></svg>

0
投票

您可以使用d3.nest()将值与汇总和求和函数相加。

var data = [
    {Date : "2017-12-15", Sales : "50"},
    {Date : "2017-12-16", Sales : "20"},
    {Date : "2017-12-17", Sales : "30"},
    {Date : "2017-12-18", Sales : "10"},
    {Date : "2017-12-18", Sales : "40"},
    {Date : "2017-12-19", Sales : "60"}
]

var nested = d3.nest()
               .key(function(d) {
                 return d.Date;
               })
               .rollup(function(v) {
                 return d3.sum(v, function(d) {
                   return d.Sales;
                 });
               })
               .entries(data);

console.log(nested);

结果数组如下所示:

[
{key: "2017-12-15", value: 50},
{key: "2017-12-16", value: 20},
{key: "2017-12-17", value: 30},
{key: "2017-12-18", value: 50},
{key: "2017-12-19", value: 60}
]

需要注意的是嵌套对象现在使用“key”和“value”作为键。


0
投票

您可以使用array#reduce来计算同一日期的Sales值。

var data = [{Date : "2017-12-15", Sales : "50"},{Date : "2017-12-16", Sales : "20"},{Date : "2017-12-17", Sales : "30"},{Date : "2017-12-18", Sales : "10"},{Date : "2017-12-18", Sales : "40"},{Date : "2017-12-19", Sales : "60"}];

var result = Object.values(data.reduce((r, o) => {
  r[o.Date] = r[o.Date] || {Date: o.Date, Sales : 0};
  r[o.Date].Sales += +o.Sales;
  return r;
},{}));

console.log(result);

var data = [{Date : "2017-12-15", Sales : "50"},{Date : "2017-12-16", Sales : "20"},{Date : "2017-12-17", Sales : "30"},{Date : "2017-12-18", Sales : "10"},{Date : "2017-12-18", Sales : "40"},{Date : "2017-12-19", Sales : "60"}];

var data = Object.values(data.reduce((r, o) => {
  r[o.Date] = r[o.Date] || {Date: o.Date, Sales : 0};
  r[o.Date].Sales += +o.Sales;
  return r;
},{}));

data.forEach(function(d) {
  d.Date = d3.timeParse("%Y-%m-%d")(d.Date)
})

var svg = d3.select("svg"),
  margin = {
    top: 20,
    right: 20,
    bottom: 30,
    left: 50
  },
  width = +svg.attr("width") - margin.left - margin.right,
  height = +svg.attr("height") - margin.top - margin.bottom,
  g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var x = d3.scaleTime()
  .rangeRound([0, width]);

var y = d3.scaleLinear()
  .rangeRound([height, 0]);

var line = d3.line()
  .x(function(d) {
    return x(d.Date);
  })
  .y(function(d) {
    return y(d.Sales);
  });

x.domain(d3.extent(data, function(d) {
  return d.Date;
}));
y.domain(d3.extent(data, function(d) {
  return d.Sales;
}));

g.append("g")
  .attr("transform", "translate(0," + height + ")")
  .call(d3.axisBottom(x))

g.append("g")
  .call(d3.axisLeft(y))

g.append("path")
  .datum(data)
  .attr("fill", "none")
  .attr("stroke", "steelblue")
  .attr("stroke-linejoin", "round")
  .attr("stroke-linecap", "round")
  .attr("stroke-width", 1.5)
  .attr("d", line);
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="600" height="180"></svg>
© www.soinside.com 2019 - 2024. All rights reserved.