Ignore duplicate date values - d3.js

I have some data that has duplicate dates in it, but the values will always be the same - how do I count occurrence only once and reflect it on a bar chart?
I'm guessing I need to setup a filter function on grouping, I'm not sure how to go about this.
The data:
var jsonStr = ([
{"date": "2011-11-14", "value": 0.1121},
{"date":"2011-11-25", "value": -0.0231},
{"date":"2011-11-25", "value": -0.0231},
{"date":"2011-11-25", "value": -0.0231}
]);
The code:
//setup dimensions
var dateDimension = ndx.dimension(function (d) {
return d.value;
});
var fluctuation = ndx.dimension(function (d) {
return Math.round(d.value *10)/10;
});
var fluctuationGroup = fluctuation.group();
fiddle: http://jsfiddle.net/wbott70/xtjJn/

This probably isn't the most efficient way to do this, but using a map is simple and short:
var uniqueValues = d3.map([])
jsonStr.forEach(function(d){ uniqueValues.set(d.date, d); });
newJsonStr = []
uniqueValues.forEach(function(d){ newJsonStr.push(uniqueValues.get(d)); });
The result:
[{"date":"2011-11-14","value":0.1121},{"date":"2011-11-25","value":-0.0231}]

The better would probably be to remove the duplicates in the data (if you never need this information), before using the Crossfilter library, using the following code, just after your definition of jsonStr:
var newJson = [];
for (var i = 0; i < jsonStr.length; i++) {
var found = false;
for (var j = 0; j < newJson.length; j++) {
if (jsonStr[i].date === newJson[j].date) {
found = true;
break;
}
}
if (!found) {
newJson.push(jsonStr[i]);
}
}
jsonStr = newJson;

Related

Parsing through a GeoJson in D3

I am having difficulty saving the names in a variable or something, found in features.properties.ADMIN as to call them for a tooltip. I wish to save them where it would simply call d.country or something for my tooltip.
d3.json('countries.geojson', function(drawMaps) {
var features = drawMaps.features
var data2;
data2 = drawMaps.parse(function(d) {
return {
country: d.features.properties.ADMIN
};
});
console.log(drawMaps.features[1].properties.ADMIN);
console.log(features[2].properties.ADMIN);
});
Edit 1.
d3.json('countries.geojson', function(drawMaps2) {
for (var j = 0; j < drawMaps2.features.length; j++) {
var jsonCountry = drawMaps2.features[j].properties.ADMIN;
console.log(jsonCountry);
break;
}
console.log(jsonCountry);
console.log(drawMaps2.features[3].properties.ADMIN);
});

filter data from csv using array filter not working as expected

My data is as follows in csv format.
Id,Title,Year,Runtime,Country,imdbRating,imdbVotes,Budget,Gross,WinsNoms,IsGoodRating
13,Alone in the Dark,2005,96,"Canada, Germany, USA",2.3,37613,20000000,8178569,9,0
38,Boogeyman,2005,89,"USA, New Zealand, Germany",4.1,25931,20000000,67192859,0,0
52,Constantine,2005,121,"USA, Germany",6.9,236091,75000000,221594911,11,1
62,Diary of a Mad Black Woman,2005,116,USA,5.6,10462,5500000,50458356,26,0
83,Fever Pitch,2005,104,"USA, Germany",6.2,36198,40000000,50071069,9,1
Im trying to filter out the data as below but none of the filtering works.
d3.csv("movies.csv", function(error, data) {
// change string (from CSV) into number format
data.forEach(function(d) {
d.imdbRating = +d.imdbRating;
d["WinsNoms"] = +d["WinsNoms"];
d["IsGoodRating"] = +d["IsGoodRating"]
});
var rating0 = data.filter(function(d){ return d["IsGoodRating"] = 0});
rating0.forEach(function(d) { console.log(d); });
//the above line does not give me anything on the console
var rating1 = data.filter(function(d){ return d["IsGoodRating"] = 1});
rating1.forEach(function(d) { console.log(d); });
//the above line gives me an output of all the records with both IsGoodRating which are 0 and 1 but the output shows as 1 which is not what the data has.
Any help will be appreciated. Im new to d3.js so I might be making a basic mistake.
doing the same as below works as expected but the array filter does not.
var rating0 = data.filter(function(d)
{
if (d["IsGoodRating"] == 0)
{
return d;
}
})
// var rating0 = data.filter(function(d){ return d.IsGoodRating = 0}); This array filter is not working for some reason
rating0.forEach(function(d) { console.log(d.IsGoodRating); });
var rating1 = data.filter(function(d)
{
if (d["IsGoodRating"] == 1)
{
return d;
}
})
// var rating1 = data.filter(function(d){ return d["IsGoodRating"] != 0});This array filter is not working for some reason
rating1.forEach(function(d) { console.log(d.IsGoodRating); });

Is there a way to make a key or legend for a heat map with dc.js?

I made a heat map with dc.js and I was wondering if there is a key or a legend function for heat maps in dc.js. I have searched the internet and can't seem to find a built in way of doing it, so has anyone else tackled this problem?
I faced this same task and what I did is I made a second heat map that is one row long from the min value to the max value.
var range = maxValue - minValue;
var heatArr = [];
for (var i = 0; i < 24; i++) {
heatArr.push({
val: minValue + i / 23 * rangeValue,
index: i
});
}
var ndx = crossfilter(heatArr);
var keyHeatmap = ndx.dimension(function(d) {
return [d.index, 1];
});
var keyHeatmapGroup = keyHeatmap.group().reduceSum(function(d) {
return d.val;
});
var heatmapChart = dc.heatMap("#heatmapKey");
var heatColorMapping = function(d) {
return d3.scale.linear().domain([minValue, maxValue]).range(["blue", "red"])(d);
};
heatColorMapping.domain = function() {
return [minValue, maxValue];
};
heatmapChart.width(400)
.height(80)
.dimension(keyHeatmap)
.group(keyHeatmapGroup)
.colorAccessor(function(d) {
return d.value;
})
.keyAccessor(function(d) { return d.key[0]; })
.valueAccessor(function(d) { return d.key[1]; })
.colsLabel(function(d){
return heatArr[d].val.toFixed(0);
})
.rowsLabel(function(d) {
return "Key";
})
.transitionDuration(0)
.colors(heatColorMapping1)
.calculateColorDomain();
heatmapChart.xBorderRadius(0);
heatmapChart.yBorderRadius(0);
minValue and maxValue were found in my original heat map. My final result looked like this:

HTML table not updating when data changed

I'm building a chart with an accompanying table. The data for both comes from html input elements with data provided by the user. For now I'm just working on getting the table to update when the user clicks the submit button.
The first time the user clicks the submit button, the table displays correctly, however, on subsequent clicks the table is not updated, even though the underlying data is correctly updated (the global variable cashflows contains the user-entered data).
The code is shown below, but I also have a jsfiddle: http://jsfiddle.net/cyclical/xcGSu/5/
(selecting the Load Sample Data button will populate some sample data).
If the table updates correctly on the first click, doesn't that indicate that the data is bound correctly to the DOM?
Thanks,
Neil
var dollars = d3.format(",.2f");
function sampleData() {
d3.select("#cf1")[0][0].value=50000;
d3.select("#dt1")[0][0].value = "2007-05-10";
d3.select("#cf2")[0][0].value = 20000;
d3.select("#dt2")[0][0].value = "2011-01-11";
d3.select("#cf3")[0][0].value = 50000;
d3.select("#dt3")[0][0].value = "2012-07-19";
d3.select("#cf4")[0][0].value = 40000;
d3.select("#dt4")[0][0].value = "2012-08-03";
d3.select("#endMV")[0][0].value = 190551.29 ;
d3.select("#endDate")[0][0].value = "2013-09-30";
}
d3.select("#sample")
.on("click", sampleData);
var cashflows = [];
var total = 0;
var irr = 0;
// bind the cashflows array to a table for display
var column_titles = ['Date','Cashflow','Days','IRR Cashflow'];
var columns = ['date','cf','days','irr_cashflow'];
d3.select("#results").selectAll('table').data([0]).enter().append('table');
var table = d3.select('table');
table.selectAll('thead').data([0]).enter().append('thead');
var thead = table.select('thead');
table.selectAll('tbody').data([0]).enter().append('tbody');
var tbody = table.select('tbody');
table.selectAll('tfoot').data([0]).enter().append('tfoot');
var tfoot = table.select('tbody');
// append the header row
thead.append("tr")
.selectAll("th")
.data(column_titles)
.enter()
.append("th")
.attr("align", function(d) {if (d=='Date') { return "left"} else { return "right"}})
.text(function(column) { return column; });
function calculateIRR(){
cashflows = [];
var cfvalues = [];
var cfdates = [];
// get cashflows
d3.selectAll("input.cashflow")[0]
.forEach(function(d,i) {
if (d.value) {cfvalues.push( 1 * d.value )};
}
)
// get dates
d3.selectAll("input.cfdate")[0]
.forEach(function(d,i) {
if (d.value) {cfdates.push( d.value)};
}
)
// get ending MV and associated date; MV is multiplied by -1
cfvalues.push(-1 * d3.select("#endMV")[0][0].value);
cfdates.push(d3.select("#endDate")[0][0].value);
// convert date strings to date objects
var dates = cfdates.map(function(d) { return new Date(d.replace(/-/g, "/"))});
// calculate the IRR; use 5% as starting value
var rate = XIRR(cfvalues ,dates, .05);
irr = rate;
var r = d3.select("#ratedisplay").selectAll("div")
.data([rate])
.enter()
.append("div")
.attr("class","rate")
.text(function(d,i) {return "IRR: " + d}); //{return "IRR:" + dollars(d) + ""});
var len = cfvalues.length;
var last_day = dates[len -1];
// construct final cashflow array for binding
for (var i = 0; i < len; i++) {
var cf_days = moment(last_day).diff(moment(dates[i]), 'days');
var irr_cashflow = FV(rate, cf_days/365 , 0, cfvalues[i],0);
total += irr_cashflow;
cashflows.push(
{'cf': cfvalues[i], 'date': dates[i], 'days' : cf_days, 'irr_cashflow': irr_cashflow}
);
};
var rows = tbody.selectAll("tr")
.data(function(d) {return cashflows} )
.enter()
.append("tr");
var cells = rows.selectAll("td")
.data(function(row) {
return columns.map(function(column) {
return {'name': column, 'value': row[column]};
});
})
.enter()
.append("td")
.attr("align",function(d) {
if (d.name == 'date') { return "left" } else {return "right"}
})
.html(function(d) {
if (d.name == 'date') {
return d3.time.format("%Y-%m-%d")(d.value);
} else {
return dollars(d.value);
}
});
rows.exit().remove();
cells.exit().remove();
}
d3.select("#submit")
.on("click", calculateIRR);

How to do Client side pagination for filtered data

YAHOO.util.Event.addListener("genes", "change", function(e) {
var value = YAHOO.util.Event.getTarget(e).value;
if(YAHOO.lang.isValue(value)) {
myDataTable.getDataSource().sendRequest(null, {
success:function(request, response, payload) {
this.initializeTable();
var rs = response.results;
var filtered = [];
for(var i = 0; i < rs.length; i++) {
//alert(rs[i].gene);
if(rs[i].gene == value) {
filtered[filtered.length] = rs[i];
}
}
this.getRecordSet().setRecords(filtered, 0);
this.render();
},
scope:myDataTable,
argument:null
});
}
});
This is my code to filter the data. i am getting the data perfectly when i change the option for selection.
but the pagination is not working it is showing as '0' even the records are displayed.
can any one plz suggest me.
Thanks!!
You can try this:
dobMenuButton.subscribe("selectedMenuItemChange",function(e) {
var value =e.newValue.value;
if(YAHOO.lang.isValue(value)) {
myDataTable.getDataSource().sendRequest(null, {
success:function(request, response, payload) {
this.initializeTable();
var rs = response.results;
var filtered = [];
for(var i = 0; i < rs.length; i++) {
if(((rs[i].dateOfBirth).format("MM/dd/yyyy")) == value) {
filtered[filtered.length] = rs[i];
}
}
this.getRecordSet().reset();
MCMPagination.paginatorvar.setTotalRecords(filtered.length,true);
this.getRecordSet().setRecords(filtered, 0);
this.render();
},
scope:myDataTable,
argument:myDataTable.getState()
});
}
});

Resources