У меня проблема, аналогичная той, что описана в DC.JS get last month value as filter.Трек и фильтр в прошлом месяце в dc.js
То есть, я хочу отображать на гистограммах стоимость акций за последний месяц (по компаниям и по типу продукции), одновременно показываю эволюцию со временем акции в линейной диаграмме.
Для этого мне нужно отслеживать последний месяц, выбранный путем чистки линейной диаграммы. Смотрите мой jsFiddle здесь: https://jsfiddle.net/BernG/wo60z64j/12/
var data = [{date:"201501",company:"A", product: "Prod1", stock:575}
, {date:"201502",company:"A", product: "Prod1", stock:325}
, {date:"201503",company:"A", product: "Prod1", stock:200}
, {date:"201504",company:"A", product: "Prod1", stock:450}
, {date:"201501",company:"A", product: "Prod2", stock:279}
, {date:"201502",company:"A", product: "Prod2", stock:93}
, {date:"201503",company:"A", product: "Prod2", stock:0}
, {date:"201504",company:"A", product: "Prod2", stock:372}
, {date:"201501",company:"A", product: "Prod3", stock:510}
, {date:"201502",company:"A", product: "Prod3", stock:340}
, {date:"201503",company:"A", product: "Prod3", stock:680}
, {date:"201504",company:"A", product: "Prod3", stock:170}
, {date:"201501",company:"B",product: "Prod1", stock:1000}
, {date:"201502",company:"B",product: "Prod1", stock:1100}
, {date:"201503",company:"B",product: "Prod1", stock:900}
, {date:"201504",company:"B",product: "Prod1", stock:1200}
, {date:"201501",company:"B",product: "Prod2", stock:1000}
, {date:"201502",company:"B",product: "Prod2", stock:1200}
, {date:"201503",company:"B",product: "Prod2", stock:900}
, {date:"201504",company:"B",product: "Prod2", stock:1200}
, {date:"201501",company:"B",product: "Prod3", stock:1000}
, {date:"201502",company:"B",product: "Prod3", stock:1100}
, {date:"201503",company:"B",product: "Prod3", stock:900}
, {date:"201504",company:"B",product: "Prod3", stock:600}];
// Reading and formatting values
var dateFormat = d3.time.format('%Y%m');
data.forEach(function (d) {
d.dd = dateFormat.parse(d.date);
d.year = d3.time.year(d.dd);
d.month = d3.time.month(d.dd);
});
// Definition of crossfilter and dimensions
var ndx = crossfilter(data)
, dimMonth = ndx.dimension(function(d){return d.month})
, dimProduct = ndx.dimension(function(d){return d.product})
, dimCompany = ndx.dimension(function(d){return d.company;});
var lastStaticDate = dimMonth.top(1)[0].month; // identify last date in full time domain
var firstStaticDate = dimMonth.bottom(1)[0].month; // identify first date in full time domain
// Definition of a function to keep track of the last date value in the brush attached to the chartMonth.
// If chartMonth object does not exist or its corresponding brush is empty (has not been brushed), then it returns the lastStaticDate
// otherwise, it returns the last date in the brush selection
var getLastDate = function(){
if (typeof chartMonth === "undefined"){ // test if chartMonth is already in the DOM, if not return lastStaticDate
return lastStaticDate;
}
else {
if (chartMonth.brush().empty()) { // if chartMonth has been created but brush does not have have a selection
return lastStaticDate;
}
else {
return chartMonth.brush().extent()[1];
};
}
};
var lastDate = d3.time.month.ceil(getLastDate()); // lastDate is snapped to return a date where we have data in the x-domain
dateBal.innerHTML = lastDate;
var grpMonth = dimMonth.group().reduceSum(function(d){return d.stock;}); // the line chart displays all values in the x-axis to show stock evolution
// Definition of custom reduce functions
function reduceAdd(p,v) {
if (p.month===lastDate){
p.stock += v.stock;
return p;
}
else {return p;}
};
function reduceRemove(p,v) {
if (p.month!== lastDate){
p.stock -= v.stock;
return p;}
else {return p;}
};
function reduceInitial() {
return {stock: 0}
};
// Application of reduce functions
var grpCompany = dimCompany
.group()
.reduce(reduceAdd, reduceRemove, reduceInitial);
var grpProduct = dimProduct
.group()
.reduce(reduceAdd, reduceRemove, reduceInitial);
var chartCompany = dc.barChart('#chartCompany');
var chartProduct = dc.barChart("#chartProduct");
var chartMonth = dc.lineChart('#chartMonth');
chartCompany
.width(400)
.height(400)
.margins({top: 50, right: 50, bottom: 50, left: 50})
.dimension(dimCompany)
.group(grpCompany)
.x(d3.scale.ordinal())
.xUnits(dc.units.ordinal)
.elasticY(true);
chartProduct
.width(400)
.height(400)
.margins({top: 50, right: 50, bottom: 50, left: 50})
.dimension(dimProduct)
.group(grpProduct)
.x(d3.scale.ordinal())
.xUnits(dc.units.ordinal)
.elasticY(true);
chartMonth
.width(400)
.height(400)
.margins({top: 50, right: 50, bottom: 50, left: 50})
.renderlet(function (chart) {
// rotate x-axis labels
chart.selectAll('g.x text')
.attr('transform', 'translate(-10,10) rotate(315)');
})
.dimension(dimMonth)
.group(grpMonth)
.x(d3.time.scale().domain([firstStaticDate, lastStaticDate]))
.xUnits(d3.time.months)
.elasticX(true);
dc.renderAll();
Решение, которое я попытался на основе только ответ на поставленный выше вопрос (который, кстати, не был отмечен, как принято) и следовать этой логике:
1) Во-первых, я пытаюсь определить последнюю дату в наборе перекрестных фильтров. После инициализации это будет последняя дата моего измерения времени, прежде чем кисть будет перемещена в линейной диаграмме. В противном случае он возвращает дату со второго элемента в размере кисти. К этой дате я применяю функцию потолка, чтобы убедиться, что дата, которую она возвращает, является точной датой в моем измерении времени.
2) Я применяю пользовательские функции сокращения, исключая данные с месяцев, отличных от текущего выбора.
Мои конкретные вопросы:
Как я могу сделать переменную (lastDate) реактивная? В консоли хорошо работает следующее: d3.time.month.ceil (getLastDate()). Однако он не реагирует на интерактивное событие чистки.
Какие изменения необходимо внести в моих пользовательских функциях сокращения, чтобы накапливать только значения, соответствующие последнему дате и исключая все остальные? По какой-то причине клиент сокращает функции, поскольку они в настоящее время определены, не аккумулировать значения запасов правильно. Например, при инициализации, если я осмотреть объект, где grpCompany проживает, он показывает стоимость акций как 0. grpCompany.all() in console
Наконец, прежде чем голосовать, чтобы пометить этот вопрос как дубликат пожалуйста, учтите следующее:
- Оригинальный пост, похоже, не имеет принятого ответа.
- Было предложение помочь, если OP предоставил рабочий jsFiddle, но ни один из них не был предоставлен.
- Я хотел сделать следующий комментарий в оригинальном посте, прося уточнить, но это было невозможно сделать, потому что у меня еще нет необходимой репутации, чтобы опубликовать комментарий.
Благодарим вас за быстрый ответ. Решение, безусловно, очень простое и работает отлично. Я просто сделал небольшое изменение в filterHandler, чтобы включить условие, где f.length == 0, поэтому я могу применить фильтр с lastStaticDate. Это позволяет отображать столбчатые диаграммы на уже загруженной загрузке страницы на основе последней даты в линейной диаграмме. – BGutierrez