Please forgive my english.
I am trying to create a line chart with ordinal scale and brushon function. I successfully set brushing on ordinal thanks to this method :
https://dc-js.github.io/dc.js/examples/brush-ordinal.html
And now I need to set the x-axis values order.
My data is like this :
[{"id_commune":4,"datation":"-30/-20","effectif":0.09,"commune":"Frejus","lieu_dit":"Les Aiguieres","departement":"83","pays":"FR","longitude":6.73703399,"latitude":43.433152,"quantite":1,"id_datation":1},
{"id_commune":4,"datation":"-20/-10","effectif":0.09,"commune":"Frejus","lieu_dit":"Les Aiguieres","departement":"83","pays":"FR","longitude":6.73703399,"latitude":43.433152,"quantite":1,"id_datation":2},
{"id_commune":4,"datation":"-10/1","effectif":0.09,"commune":"Frejus","lieu_dit":"Les Aiguieres","departement":"83","pays":"FR","longitude":6.73703399,"latitude":43.433152,"quantite":1,"id_datation":3},
{"id_commune":7,"datation":"20/30","effectif":0.33,"commune":"Nimes","lieu_dit":"Solignac","departement":"30","pays":"FR","longitude":4.36005399,"latitude":43.836699,"quantite":1,"id_datation":6},{"id_commune":6,"datation":"20\/30","effectif":0.6,"commune":"Muralto","lieu_dit":"Liverpool b","departement":"TI","pays":"CH","longitude":8.80560809,"latitude":46.1729618,"quantite":1,"id_datation":6},
{"id_commune":4,"datation":"20/30","effectif":0.09,"commune":"Frejus","lieu_dit":"Les Aiguieres","departement":"83","pays":"FR","longitude":6.73703399,"latitude":43.433152,"quantite":1,"id_datation":6},{"id_commune":1,"datation":"20/30","effectif":0.14,"commune":"Aislingen","lieu_dit":"NP","departement":"Lkr. Dillingen an der Donau BY","pays":"DE","longitude":10.4559987,"latitude":48.5065603,"quantite":1,"id_datation":6},]
My crossfilter dimension and group look like this :
var ndx = crossfilter(records)
var graphDim = ndx.dimension(function(d) {return d.datation});
var graphGroup = graphDim.group().reduceSum(function(d) {return d.effectif;});
And the chart :
lineChart
.width(950)
.height(350)
.margins({top: 10, right: 50, bottom: 35, left: 30})
.dimension(graphDim)
.keyAccessor(function(kv) { return graphGroup.ord2int(kv.key); })
.group(graphGroup)
.x(d3.scaleLinear().domain(linear_domain))
.xAxisLabel("Chronologie")
.yAxisLabel("Effectif")
.brushOn(true)
.renderArea(true)
.renderHorizontalGridLines(true)
.renderVerticalGridLines(true)
.elasticY(true)
.yAxis().ticks(4);
Right now, I get this :
The result I am trying to accomplish is the same chart but with x-axis ticks values ordered like this :
"-30/-20
-20/-10
-10/1
..."
Any help appreciated. Thank you!
Welcome to Stack Overflow. For future reference, it helps if you can include a reproducible example, for example a jsFiddle.
I understood what you were doing because I wrote the ordinal brushing example, but you didn't include all the code, so it wouldn't be clear to others.
Here is a fiddle with complete code, and here is the relevant code:
var graphDim = ndx.dimension(function(d) {return d.datation});
var graphGroup = graphDim.group().reduceSum(function(d) {return d.effectif;});
graphGroup = ordinal_to_linear_group(sort_group(graphGroup, function(a, b) {
return d3.descending(a.value, b.value);
}));
line = dc.lineChart('#line');
var linear_domain = [-0.5, data.length - 0.5];
line
.width(950)
.height(350)
.margins({top: 10, right: 50, bottom: 35, left: 30})
.dimension(graphDim)
.keyAccessor(function(kv) { return graphGroup.ord2int(kv.key); })
.group(graphGroup)
.x(d3.scaleLinear().domain(linear_domain))
.xAxisLabel("Chronologie")
.yAxisLabel("Effectif")
.brushOn(true)
.renderArea(true)
.renderHorizontalGridLines(true)
.renderVerticalGridLines(true)
.elasticY(true)
line.yAxis().ticks(4);
line.xAxis()
.tickValues(d3.range(data.length))
.tickFormat(function(d) { return graphGroup.int2ord(d); });
Here is the (bad) result:
As its name implies, sort_group() creates a fake group sorted by the ordering function. Right now it's sorting by value, from highest to lowest:
sort_group(graphGroup, function(a, b) {
return d3.descending(a.value, b.value);
})
It looks like you want to sort by the numeric value of the first part of each key. You can change the sort accordingly:
sort_group(graphGroup, function(a, b) {
return d3.ascending(+a.key.split('/')[0], +b.key.split('/')[0]);
})
This splits each key by /, then takes the first item ([0]), then converts it to a number (+), before using d3.ascending to specify sorting from low to high.
The result:
And a working version of the fiddle.
I have three charts rendering using dc.js and all of them render a black area below or above the line. I looked through the dc.css file for any fill options that were relevant, but I couldn't find any that had a positive effect.
I', using Angular 7 as the framework to develop my application.
Json Data is in this form and has a few different device types:
{
device_ID: "DHT11-3fe381"
device_type: "thermometer"
time: "2019-02-26T00:56:54.000Z"
value: 25.9
}
I use crossfilter to create a timeDim dimension and sort each value according to device_type:
const timeDim = ndx.dimension((d) => d.time);
var Thermo = timeDim.group().reduceSum((d) => {
if (d.device_type === 'thermometer' && d.value <= 40) {
return d.value;
} else {
return 0;
}
});
Then, I create my graphs:
const DTchart = dc.compositeChart('#graphT');
DTchart
.width(800)
.height(300)
.margins({top: 10, right: 50, bottom: 100, left: 60})
.dimension(timeDim)
.group(device, 'value')
.xUnits(d3.timeMinutes)
.x(d3.scaleTime().domain([bottomDate, topDate]))
.yAxisLabel('Thermometer reading')
.xAxisLabel('Time')
.brushOn(false)
.elasticX(true)
.elasticY(true)
.controlsUseVisibility(true)
.renderHorizontalGridLines(false)
.compose([
dc.lineChart(DTchart)
.dimension(timeDim)
.renderArea(false) // This didn't contribute anything
.colors('RED')
.group(Thermo)
.valueAccessor((d) => d.value)]
);
The default for an SVG path element, which is used for line charts, is to display filled in black,
If you include dc.css it will set fill: none. The axis font will fit better and the axis lines will be narrower too.
You didn't ask, but I think the vertical red lines are due to zeros in your data. If data is missing you could consider using lineChart.defined to put gaps in your lines instead of dropping to zero.
As the title mention we are not able to hover over point thats are behind a path.area.
The situation is the following
If we hover the blue and the yellow line we are able to get the tooltip but if we hover over the red line we get the tooltip only from the first and the last point.
The code is the following:
let nix = crossfilter();
timeseriesFiltered.forEach(ts => {
ndx.add(ts.values.map(function(d) {
let temp = JSON.parse(JSON.stringify(objTemplate));
temp[ts.place] = d.value;
temp.date = new Date(d.timestamp);
return temp;
}));
});
let dimDate = ndx.dimension(dc.pluck('date'));
let lineChartGroups = [];
timeseriesFiltered.forEach((ts, index) => {
let group = dimDate.group().reduceSum(dc.pluck(ts.place));
let lineChart = dc.lineChart(composite)
.dimension(dimDate)
.renderDataPoints(true)
.renderArea(true)
.defined(d => {
return d.y != 0;
})
.colors(this.colors[index])
.group(group, this.setName(ts.place));
lineChartGroups.push(lineChart);
})
let chart = composite
.width(width)
.height(300)
.margins({top: 30, right: 60, bottom: 30, left: 60})
.x(d3.scaleTime().domain([new Date(minDate), new Date(maxDate)]))
.yAxisLabel(timeseriesFiltered[0].unit)
.elasticY(true)
.mouseZoomable(true)
.brushOn(false)
.clipPadding(10)
.legend(dc.legend().x(80).y(20).itemHeight(13).gap(5))
._rangeBandPadding(1)
.compose(lineChartGroups);
chart.render();
We have tried to raise all the circle dot by using the following statement:
d3.selectAll('circle.dot').raise();
But it didn't work. Any suggestion?
I'm not sure that it's a great idea to use renderArea in a composite chart; as you can see, the colors get muddied together into brown, and it's not really clear what it's supposed to convey.
I think renderArea works better with a stacked chart, where the area that is covered by each color means something.
That said, it's pretty easy to fix the problem you are seeing.
The reason why raising the dots doesn't work is because each child of the composite chart is in its own layer. So raising the dots only puts them at the top of that chart (where they already are).
Instead, you can disable mouse interactions for the filled areas:
path.area {
pointer-events: none;
}
Since the filled areas weren't interactive before, this shouldn't lose much, but you might want to be more conservative and restrict the rule to the particular chart with the selector #composite-chart path.area
How can I have the labels outside the bar in a row chart with dc.js?
I'd like a graph like this:
however, the labels are inside the actual bars... is there any settings i need to change to have it like this?
I finally got this working and here is the trick,
As mentioned by the Gordon it can be done on renderlet.
First I have gave the margin for my row chart ,
.margins({ top: 20, right: 20, bottom: 40, left: 110 })
Then took the label outside by giving x value in negative.
.labelOffsetX(-10)
This will perfectly move our label but its still need some style changes to look fine and that need to be done on renderlet,
.on('renderlet', function (chart) {
chart.selectAll("g.row text")
.style("text-anchor", "end")
.call(function (t) {
t.each(function (d) {
var self = d3.select(this);
var text = self.text();
if (text.length > 14) {
self.text('');
text = text.substring(0, 14) + '..';
self.text(text);
}
})
});
})
You can ignore .call() function as I place this just to make sure my label length does not cross certain limit.
Hope that work for you.!
This example (http://dc-js.github.io/dc.js/crime/index.html) looks great but the path elements and SVG for the map of Canada have been defined manually. I'd like to draw a world map with geoChoroplethChart and then add a bubbleOverlay.
I've tried them separately and recently tried a compositeChart approach:
compositeChart.width(1440)
.height(500)
.margins({top: 10, right: 50, bottom: 30, left: 60})
.compose([
dc.geoChoroplethChart("#us-chart")
.dimension(countries)
.projection(projection)
.group(countryValue)
.colors(d3.scale.category10())
.colorDomain([0, 3])
.colorCalculator(function (d) { return d ? geoChart.colors()(d) : '#ccc'; })
.overlayGeoJson(statesJson.features, "state", function (d) {
return d.properties.name;
}),
dc.bubbleOverlay("#us-chart")
.svg(d3.select("#us-chart svg"))
.dimension(countries)
.group(countryValue)
.radiusValueAccessor(function(p) {
//console.log(p);
return p.val;
})
.r(d3.scale.linear().domain([0, 4]))
.point("Angola",200,200)
])
dc.renderAll();
I have a sneaky feeling compositeChart will only work with charts based on a grid system, like line and bar charts. Is this right? In which case, is there a way to add a bubbleOverlay to a choropleth in DC, without doing it manually?