I'm currently plotting a list of numbers (y-axis) against a list of titles (x-axis). Each number can correspond to multiple websites. Right now I've been using the ascending function provided by d3 to sort them. I've currently got a drop-down menu in which I can pick either number or title and each option individually sorts by the respective choice. However, I was wondering if there was a way so that I could sort alphabetically by title, and then keeping it alphabetical, also sort by number. As of now I can only do one or the other.
Example:
My data is stored in a CSV like this:
"id","name"
1,"youtube"
1,"google"
2,"google"
3,"nike"
4,"google"
Then I use
d3.csv("csvTestFile.csv", function (dataset)
to read in the file and I convert the id number to ints.
To sort I do the following:
data.sort(function(a, b) { return d3.ascending(a.id, b.id)});
To sort by ID. To sort by name I do this:
data.sort(function(a, b) { return d3.ascending(a.name, b.name)});
Both of these work properly, however I would like to first sort by ID, then also sort by Name. So the axis would display (starting from the origin) 1, 2, 3, 4 up the y-axis, and google, nike, youtube down the x-axis. Right now if I try to sort it will either be 1, 2, 3, 4 up to the y-axis and youtube, google, nike down the x-axis OR google, youtube, nike down the x-axis with 1, 2, 4, 3 up the y-axis.
What I want is 1, 2, 3, 4 up the y-axis (sorted numerically) and google, nike, youtube down the x-axis (sorted alphabetically) at the same time. Given this is a scatterplot it should be something simply like rearranging the ticks on the axis but I'm not quite sure how to go about doing it.
The order in which input values are mapped to output values for a categorical scale depends on the order in which they are given to .domain(). All you need to do to achieve what you want is to sort the values accordingly when you create the scale, i.e. something like
var scale = d3.scale.ordinal()
.domain(data.sort(function(a, b) { return d3.ascending(a.name, b.name); }))
.range([...]);
Related
I am struggling with D3. I have a dataset that I am pulling into D3, and populating a bar chart. The problem is there are too many bars! I want to only display the top 10 values.
My csv has two values, the key (column header) is "Name" and the value is "NumberOfTickets". I want to show only 10 names that have the most tickets. I assume i need to sort and splice my dataset, but I have tried everything and cant get it to work. It seems most tutorials are geared towards simple arrays and not a dataset that comes from a CSV with key value pairs. Any help would be appreciated. Here is my dataset portion of the D3 code. I assume this is where I need to manipulate the dataset:
var report = data.forEach(function(d){
d.Name= d.Name;
d.NumberOfTickets= +d.NumberOfTickets;
});
Try this:
var report = data.sort(function(a, b) {
return d3.descending(+a.NumberOfTickets, +b.NumberOfTickets);
}).slice( 0, 10);
If you want the names that get less tickets, just change for "ascending". If you want to change your slice, remember that the start number is inclusive, but the ending number is not.
For preparing graphs from data that exists in MySQL tables, I am using DimpleJS framework. I am able to plot graphs, everything works. One question though -
In a simple bar chart, with category values on X axis and measure values on Y axis, is there a way to limit the number of X axis categories being displayed? Example, let's say this is my data set: [(A,1), (B,2), (C,1), (D,5), (E,4)]
So in my dataset, there are 5 categories (X axis - A, B,C,D,E) and corresponding measures that I will be displaying in Y axis. Question is, I just want to display only 3 of the measures - let's say only first three, in this case (A,1), (B,2) and (C,1), although my dataset has two more (D,5) and (E,4).
Is there any way to restrict it in JS/ DimpleJS? I have limited control on the dataset that is coming in.
Thanks.
Use dimple.filterData after you receive the dataset but before you provide the data to dimple. This does not mutate the data so won't affect any other operations. I'm not sure what your actual category field is but it should look similar to this :
var chartData = dimple.filterData(originalDataset, 'category', ["A", "B", "C"]);
var chart = new dimple.chart(svg, chartData);
Otherwise there is not a provided way to restrict a category axis from showing values present in the data.
I'm using Highcharts for a project in which I have to display two series with about a thousand points each. The x-axis represents a date, and the y-axis a quantity. In addition, each point has an associated list of namesMy data is day-by-day without gaps, with a structure such as
var mydata = [ ...
{x: theDate, y: theValue, names: theNames},
... ]
where theNames is an array of strings. I can access these in the tooltip formatter through this.points.point.names, given that the range displayed on the chart is small enough. If I change the x-axes so that the start date and end date are more than roughly a year apart, then the tooltip is not rendered at all.
One of the possible avenues that I have tried but failed with so far is setting the turboThreshold limit to the length of the longest series plus 1. Setting this lets me at least display a graph when mydata.length > 1000 (the default value). However, this only displays the tooltip if the x-axis range is less than 261. Otherwise, the tooltip disappears entirely, as does the point.data object where I'm getting the name from.
I'm also not great at JavaScript, but I was wondering if there were a way to separate the names of the points from the array containing them (in my examples, myData1 and myData2) and somehow access those names from the tooltip function without going through the current point.
Here is the link to the jsFiddle demonstrating this issue.
All help is appreciated!
The problem is in dataGrouping, when disabled works fine: http://jsfiddle.net/34tfg/1/
DataGrouping is method in Highcharts to approximate points and display them when width of the chart is not enough, e.g. how to display 10 000points in a chart of width 1 000px -> 10 points in a one pixel..? And when dataGrouping is used, new points are created, so all your custom options like 'names' etc. are lost (at least not accessible).
Code:
plotOptions: {
line: {
dataGrouping: {
enabled: false
},
turboThreshold: 10000
}
},
Possible duplicate question to Bar chart in Javascript: stacked bars + grouped bars
I'm trying to create a stacked bar chart that lets you compare 2 values (dark and mid blue) to last week's data points (the secondary light blues 'behind').
Starting with multiBarChart() with .stacked(true) first I tried merging both weeks into a single array of 14 bars, where the x position could help group the bars. I tried to form my combined array of objects where .x properties' values are 0, 0.3, 1, 1.3, 2, 2.3, etc.
Unfortunately unlike lineChart() it doesn't use the x value for positioning.
Another idea is to exploit the group .stacked(false), providing 4 items (instead of 2) with the same x value. These then appear overlaid on top of each other instead of stacked.
Here the spacing looks good, but how do I stack these 2 by 2?
Hey I just developed grouped+stacked bar chart on d3.js. It is not NVD3 but it may help you.
Source
Demo
Let me just say up front that I am SO not an nvd3 expert. I'm barely past the getting-started stage myself.
That said, it looks like you're making this too hard on yourself.
I think you really want to send nvd3 two sets of data, with the x's matching between the two. (E.g., (1,y1a) corresponding to (1,y2a), then (2,y2a) with (2,y2b), etc.)
You can see this more clearly by the following:
Head to their Live Code page
Select the Group/Stacked Bar Chart.
Select the Data (JSON) tab.
Replace the first function with the following, and observe the resulting x values.:
function() {
return stream_layers(2,10,.1).map(function(data, i) {
alert( 'Stream '+i+': '+JSON.stringify(data));
return {
key: 'Stream' + i,
values: data
};
});
}
Best as I understand it, that's the model you're looking for.
I want to use the Highcharts' Master detail chart as visualized here: http://www.highcharts.com/demo/dynamic-master-detail
However, I don't want to use intervals in order for the script to automatically assign Date values to each point of data, because my data are not necessarily continuous. E.g. I might have data for one minute and nothing for the next minute.
Ideally, I want to visualize three days in this chart. Each point will be a value of a specific minute of a specific date.
Any suggestions how I can do that? I don't mind using other libraries, if that's necessary.
Let me know if I didn't make myself clear or if you need more information.
Thank you.
The data properties in the series object can except either an array of values, in which case it will assume data to be equally spaced. Alternatively you can pass an array of arrays, where the outer array has size same as number of points, and each element of this array is another array of size 2, with first element as epochTime and the 2nd being the value. There is also a third option as explained below
Documentation # http://www.highcharts.com/stock/ref/#series--data
Excerpt of the documentation
data : Array<Mixed>
An array of data points for the series. The series object is expecting the points to be ordered from low to high. The reason for this is to increase performance. While in many cases the data is fetched from a server, it's also more convenient to sort on the server and thereby save on client resources. The points can be given in three ways:
A list of numerical values. In this case, the numerical values will be interpreted as y values, and x values will be automatically calculated, either starting at 0 and incrementing by 1, or from pointStart and pointInterval given in the plotOptions. Example:
data: [0, 5, 3, 5]
A list of arrays with two values. In this case, the first value is the x value and the second is the y value. If the first value is a string, it is applied as the name of the point, and the x value is incremented following the above rules. Example:
data: [[5, 2], [6, 3], [8, 2]]
A list of object with named values. In this case the objects are point configuration objects as seen under options.point. Example:
data: [{
name: 'Point 1',
color: '#00FF00',
y: 0
}, {
name: 'Point 2',
color: '#FF00FF',
y: 5
}]
View JSFiddle Example