I am plotting Vertical Grouped Bar Chart from a csv file which contains Discount, Rating and Clicked. The data is csv is like 55,2,1 and 40,5,0 etc. Here the first value(55,40) are the discounts, (2,5) rating and 1 and 0 correspond to clicked and not clicked respectively. On plotting the chart with following code.
var svg2 = dimple.newSvg("#discountContainer", 590, 400);
d3.csv("/svm1000.csv", function (data) {
var myChart2 = new dimple.chart(svg2, data);
myChart2.setBounds(60, 30, 510, 330)
myChart2.addCategoryAxis("x", ["rating", "action"]);
var y = myChart2.addMeasureAxis("y", "discount");
//y.tickFormat = "%";
myChart2.addSeries("action", dimple.plot.bar);
myChart2.addLegend(65, 10, 510, 20, "right");
myChart2.draw();
});
The problem is I want to represent y axis in percentage in multiple of 10, like 0%, 10%, 20% .. 100%. Right now the y axis values are like 0,2k,4k,6k...20k. So how to represent y axis in percentage.
I see this question is old, so this answer may not help you, but for others facing similar requirements this might be helpful.
dimple.js provide method to have percentage series
myChart2.addPctAxis("y", "discount");
but remember you can't create both Value and Percentage in same axis, you might need to have dual axis graph
var x = myChart2.addCategoryAxis("x", ["rating", "action"]);
var y1 = myChart2.addPctAxis("y", "discount");
var y2 = myChart2.addMeasureAxis("y", "amount"); // the field with value ranges 1000...
also you don't able to use grouped bar chart; for axis 1 use bar chart and for axis 2 use line or vice versa like
myChart2.addSeries("action", dimple.plot.bar, [x, y1]);
myChart2.addSeries("action", dimple.plot.line, [x, y2]);
Related
I am having time series chart in D3js in that I am setting up yScale like.
setYScale() {
this.yScale = d3
.scaleBand()
.range([this.gHeight, 0])
.domain(this.yData) //this is array [0,1,2,3,4,5....23]
.padding(0.06);
},
This sets tick for me in left side, from 0 to 23 (24hrs), what I would like to achieve is that instead of having it sequential order from 0,1,2,3,4...tick I would like to have 0,2,4,6,8 (even numbers), and rest should work be as it is just ticks I would like to have it as even number. Can anyone help me on this.
Your code is just the scale, assuming you have an axis called axis, try:
axis.tickFormat(function(d) { return (+d)%2 ? '' : d })
I'd like to plot the top X values of a dimension in a row chart, ideally labeled using one dimension but using the value of another for the size of the bars.
Essentially a presentation of data like the following:
Sally: 1
Fred: 0.7
Bob: 0.5
Francis: 0.4
George: 0.2
Sam: 0.18
Susan: 0.16
Sarah: 0.15
Tom: 0.15
Simon: 0.14
...
rowChart1 = dc.rowChart('#id')
valDim = ndx.dimension(function(d) {return d.data});
valGroup = valDim.group().reduceCount();
rowChart1.dimension(valDim).group(valGroup);
Plots the value counts, rather than the values themselves.
Specifically I'm looking to make a rowChart of the top N data points, where the length of the bars is determined by the value of the data points, not the number of data points with that value.
I.e. Sally would have her own bar, and it would be 100% of the x-axis, while Fred's bar would be 70% and Simon's bar would be 14% of the x-axis.
If I understand your question correctly, the conceptual problem may be the distinction between the crossfilter definition of dimension, which means "a column that you bin and filter on", versus the English/math definition of the word, which might mean "any column of data" or might mean a geometric direction on a chart.
There's always at least one geometric "dimension" on every chart which is not associated with a "crossfilter dimension" because it is aggregated. In a line chart Y is driven by a group reduction/aggregation; in the row chart X is.
I understand you have a column in your data which is a unique key, say name, which you want to map to the row Y axis, and you have a second column x, which you want encode in the row X axis without aggregation. You can use crossfilter's group.reduceSum() and since only one record will land in each bin, the sum of x is just x.
Since name is a unique key, there will be only one x per name.
Let's say you have data like this:
const data = [
{name: 'Sally', x: 1},
{name: 'Fred', x: 0.7},
{name: 'Bob', x: 0.5},
{name: 'Francis', x: 0.4},
{name: 'George', x: 0.2},
{name: 'Sam', x: 0.18},
{name: 'Susan', x: 0.16}
// ...
];
Then the crossfilter initialization might look like this:
const xf = crossfilter(data),
dim = xf.dimension(d => d.name), // bin and filter on this
group = dim.group().reduceSum(d => d.x); // here be values
and chart
const rowChart = dc.rowChart('#row');
rowChart
.dimension(dim)
.group(group)
.render();
Demo fiddle
This might sound really complicated if you just want to plot x against some names, but dc.js and crossfilter are optimized for the case where there will be filtering between charts. No matter what they draw, crossfilter will always filter the rows, sort the rows into buckets, and reduce those buckets.
If you don't use filtering, then these libraries are overkill. But if you do want to filter, it's really nice to have a library with a data model that takes care of it.
I am trying to create a simple column chart using an array of data points of the form[datetime,value], for example [1422345600000,146]. I would like to plot these with the date on the x-axis with labeled ticks every few days. I almost managed to accomplish this, but the first couple of ticks are spaced oddly close together.
You can see it here: http://jsfiddle.net/9r4fqbnm/2/
I tried
var xAxis = d3.svg.axis()
.scale(x)
.orient('bottom')
.ticks(d3.time.days,7)
.tickFormat(d3.time.format("%m/%d/%Y"))
and the ticks after the first two are indeed spaced by 7 days.
I didn't find this issue online--am I missing something obvious?
Thanks
Your problem is your data array. I was too lazy to dig into each value and see which one is the culprit, but basically by converting it into a human readable format and making sure the values are valid - fixes the problem:
function getDate(y, m, d) {
return new Date(y, m, d);
}
var data = [
[getDate(2015, 1, 27), 146], [getDate(2015, 1, 28), 132], ..., [getDate(2015, 2, 24), 67], [getDate(2015, 2, 25), 46]
];
var startDate = data[0][0];
var endDate = data[data.length - 1][0];
...
http://jsfiddle.net/2L3fy90j/1/
I made a histogram / bar graph. I read in my frequency data as integers and set up my y-axis like this:
var yScale = d3.scale.linear().range([300, 0]).domain([0, 2]);
var yAxis = d3.svg.axis().scale(yScale).orient(‘left’)
.tickFormat(d3.format(,.0f));
Unfortunately, the y axis repeats each frequency several times as shown here:
How do I tell d3 to stop repeating y-values on the y-axis? I don’t want to use .ticks(someNumber) since I want to keep the number of ticks itself flexible.
I needed mine to be dynamic, this worked for me: [Version 4]
var y = d3.scaleLinear().range([height, 0]);
var yAxis = d3.axisLeft()
.scale(y)
.tickFormat(d3.format("%d"));
// Reset the axes domains with new data
y.domain([0, d3.max(data, function (d) { return d.value; })]);
if (y.domain() [1] < 10) {
yAxis.ticks(y.domain()[1])
// 2 ticks
//yAxis.tickValues(y.domain());
}
// Add the y-axis with a transition
yAxisG
.transition()
.duration(500)
.call(yAxis);
Use .ticks(n) instead of tickFormat() on your axis. The ticks() function defines how many ticks d3 should target - it's not always exactly that number. It chooses the most sane division unit on its own. n is 10 by default but you could change it depending on the domain, so for the example data you could set it to 3 (0,1,2). You could theoretically also use it on data enter.
Is your graph's range/height dynamic depending on data? In most cases you don't want that as it's unpredictable. And if you set your graph's height explicitly anyway you DO want to limit the number of ticks and labels to a number best suiting that size.
You might also want to look into https://github.com/mbostock/d3/wiki/Quantitative-Scales#linear_nice . That allows you to define rules for your ticks.
I have a d3 graph that uses a linear scale for its x axis. It looks something like this:
...
y |
|
+-------------------------------------------
0.0 0.5 1.0 1.5 2.0 2.5 3.0
Time in weeks
Beneath this axis I want to display rows of data aligned to the x axis. Like this:
23 23 22 19
Using this data:
var nums = [23, 23, 22, 19];
var times = [0, 0.5, 1.5, 3];
times are where the nums should fall on the Time in weeks x axis. So the first index of nums falls under 0.0, the second under 0.5, and so on.
The scale function looks something like this:
var x = d3.scale.linear().domain([0,3]).range([0, 600]);
So x(0.5) returns the correct range value for displaying a tick on the new axis. But what I want to display is the corresponding value from the nums array. That is, display the value of nums[times.indexOf(0.5)].
Is there a way to override scale() as used by d3.svg.axis() so that it displays nums values instead of times values while still using times as the input domain?
Edit
Here is a demo
Edit 2
I figured it out thanks to ne8il's answer. The answer was not complete, but it formed the basis for this code:
var x1Axis = d3.svg.axis()
.scale(x1)
.ticks(nums)
.tickValues(times)
.tickFormat(function(x){return nums[times.indexOf(x)];})
Working example
I believe in this case you can do
d3.svg.axis().ticks(times).tickValues(nums);
It will pass each 'time' into your scale function to map it to an x coordinate, and use the corresponding indexed value in 'nums' to output text.
Source is here