I have the following snippet of code which updates my chart type from one type to another.
chart.series.forEach(function(serie){
serie.update({
type: type,
stacking: stacking,
})
})
I can pass different values in from type to stacking.
If I want my new chart to use a different array of values, the arrays of which are already defined and contain data from the database; how would I do it?
The reason I wish to do this is because I have two values, which are entered in their own arrays, say for example, 40 and 50 from a database. These are then stacked in a column chart (It's the only way I can stack).
I've created another array to store both these values in the one array when deciding to show it in a pie chart (not stacked).
I've tried adding 'data:arrayName' in as a property but this prevents my chart from rendering. Any idea guys?
Thank you.
EDIT: My problem probably only required one object to call. I don't have that much going on so the solution in the possible duplicate isn't really helpful to me. The duplicate code is trying to generate a new array on the fly using loops, I already have an array in place, I'm just figuring out how to update the array once the chart has changed to another type.
Related
I have a dataset in csv and it looks like below.
country,col1,col2,col3
Germany,19979188,11233906,43.7719591
UK,3839766,1884423,50.92349378
France,1363608,796271,41.60557873
Italy,957516,557967,41.72765781
I'd like to drop col1, col2 off while keeping country and col3. If possible, I'd like to wrap it into a function where I can pass column list that I'd like to drop/keep.
Using pandas, which I'm familiar with, I can easily do it. e.g. data.drop(['col1', 'col2'], axis = 1). But I found d3 way or js way in general is based on each row so couldn't come up with an idea to drop columns.
I was thinking of d3.map() taking desirable columns only. But I was stuck to build a general function that the column list can be passed in.
Could anyone have thoughts?
D3 fetch methods, like d3.csv, will retrieve the whole CSV and will create an array of objects based on that CSV. Because of that, filtering out some columns is useless. Actually, it's worse than useless: you'll spend time and resources with an unnecessary operation.
Therefore, the only useful solution is, if you have access and own that CSV, creating a new CSV without those columns. That way you'll have a smaller file, faster to load. Otherwise, if you cannot change the CSV itself, don't bother: just load the whole thing and use the columns you want (which will be properties in the objects), ignoring the others.
Finally, if you have a lot of data manipulation it might be interesting reducing the size of the objects in the data array. If that's your case, use a row function to return only the properties you want. For instance:
d3.csv(url, function (d){
return {country: d.country, col3: d.col3}
}).then(etc...)
I'm using highcharts / highstock and their documentation.
I need to dynamically add a series (once after the original chart data is loaded) and I need to hide the series to not be shown into the chart (but still to exist).
The reason for this is, I need to apply indicators to a certain time range and for this I'm using the hidden series (which actually works).
I also need to be able to access to the data of the hidden series at any time, but here is where my issue appears. If I try to access to my hidden series like:
console.log(chart.get('hidden-series').data);
then this returns an empty array.
I have the full code in the following jsfiddle and here is a short explanation of what I'm doing there:
With a click on the first two buttons, I'm dynamically adding two series series2 and series3. One of them is added "normally" (it's visible) and the other is added to not be visible on the chart (using the false, false as second and third parameters in the method addSeries - which I'm not sure what actually this means, since this was a legacy code and I can't find the proper documentation for this anywhere).
And then with the last buttons I'm trying to get the data for each of the series. As you can notice from my test example, even that the series3 is added (it's not visible) when trying to get the data, it's an empty array.
If I comment the two false parameters in the line:
}, false, false);
the data will be retrieved as expected, but the series will be displayed (and this is not what I want).
Is there any other way for getting the data from invisible series? Or maybe the proper description for the parameters in the addSeries method can also help in understanding the issue.
EDIT: (add the reason why I need this, based on the comments below)
The reason that I need this feature is: I need to have the VWAP indicator on the chart and to be applied only for the current day (so starting from 00:00 until the current moment), while the chart itself contains data for multiple days.
So what I'm doing is: I'm taking the subset of the data that represents the current day only, hide this subset and use it's data to show the VWAP indicator only for this certain time range.
The initial load of the indicator works as expected. I need to have access to this data, since the chart is updating in real time and I need to be able to dynamical add new points in the general series of data and but also in the hidden subset for the current day as well.
Regarding docs: you use only part of docs, the one describing options, not methods. You can find methods and props in "Classes" tab, for example addSeries: https://api.highcharts.com/class-reference/Highcharts.Chart#addSeries - the params you have set to false are animation and redraw - definitively not what you want to achieve :)
To achieve what you need you should:
add the third series just like the first one (with redraw=false)
hide this series with series.visible and series.showInLegend options set to false (if you have disabled legend, no need to set showInLegend)
Now the question is why you need series.data. The only reason to use Point Class instances is to call methods like point.remove() or point.update(). Since that one series is always hidden, then I think it's not the case.
If you don't need real Points, just some data from it, then you always have access to the dataset you used to create the series, right? Like chart.addSeries({ data: [ ... ]}).
Anyway, you can force generating points this way: https://jsfiddle.net/BlackLabel/nqsemy3z/2/ - note that series.processData() and series.generatePoints() methods are not part of API.
I have a simple datatable using dc.js. Fiddle here (https://jsfiddle.net/7p5d8g0y/)
My data emerges from the datastore in the following format. Note the array for the category value.
[{"Id":"1","InDate":"31/10/2015","Type":"New","Category":["X1"],"Value":"1.400874145"},
{"Id":"2","InDate":"21/10/2014","Type":"Old","Category":["X1","X2"],"Value":"0"},
{"Id":"3","InDate":"21/10/2014","Type":"New","Category":["X1"],"Value":"4000.4645645665"}]
I then flatten the data out so that there are multiple lines for the multiple category entries
[{"Id":"1","InDate":"31/10/2015","Type":"New","Category":"X1","Value":"1.400874145"},
{"Id":"2","InDate":"21/10/2014","Type":"Old","Category":"X1","Value":"0"},
{"Id":"2","InDate":"21/10/2014","Type":"Old","Category":"X2","Value":"0"},
{"Id":"3","InDate":"21/10/2014","Type":"New","Category":"X1","Value":"4000.4645645665"}]
The problem is that now I have multiple entries in the datatable for each category. ie see the entries for Id 2
In this instance I only care about displaying the unique ids entries in the datatable.
So my question is how would I go about displaying unique entries in the datatable? Should I be modifying the data from the data source or can I achieve what I want as is?
btw I tried implementing a fake dimension as per this SO question but couldn't get it to work
There are probably quite a few ways to fix this. I'll just mention two possibilities.
Use a dimension with array-based keys. The community fork of dc.js supports "tag" dimensions, where a row can be associated with multiple key values. If I understand correctly, you would not need to flatten your data if you use this feature.
Use a group instead of a dimension for your data table. This works, as shown in this example, as long as you are okay with descending order. This way you are displaying aggregated data instead of the raw rows. If you need ascending order, you can wrap your group using this adaptor which adds a .bottom(N) method:
function reversible_group(group) {
return {
top: function(N) {
return group.top(N);
},
bottom: function(N) {
return group.top(Infinity).slice(-N).reverse();
}
};
}
I’m trying to use data from multiple GoogleSheets to produce a single HighChart graph.
I’d like to do this without moving all the data into one area of a single spreadsheet, particularly as I want to use the drilldown option which would make it difficult to collect all the data together.
I thought I could pass the columns as an array and then reference the array in the data property of my chart, but I’m struggling to do that with even one column from one sheet.
I have searched for answers online, but I have not found anything relating to highcharts getting data from multiple sources.
Previous Research:
Using GoogleSheets Data as an array before creating the chart: (Removed Link) - The problem is that I could only use one GoogleSheets reference here as the chart object sits inside the data object.
API documentation - (Removed Link) – tells me I can access the columns but that’s not the part I’m having problems with
Querying the Chart: (Removed Link) - I have actually considered making hidden charts, then interrogating the data and making new charts from those, but that seems like a very long way round and I’m still not sure I could grab all the data I need.
Using two GoogleSheets for separate charts on the same page: (Removed Link) I have done this.
Please could you help me to understand how I can access the properties and methods of this object outside of the object itself?
Thank you.
My Code:
//Function to produce a data array ***Not Working - Cannot extract array from object method***
function getData(){
Highcharts.data({
googleSpreadsheetKey: '12x66_QEkTKg_UzvpHEygdTmfnu7oH81pSQYn78Hxt80',
googleSpreadsheetWorksheet: 4,
startColumn: 16,
endColumn: 22,
startRow: 63,
endRow: 76,
parsed: function (columns) {
var dataTest2 = [];
var columnLength = columns[1].length;
for (i = 0; i < columnLength; i = i + 1) {
dataTest2.push(columns[1][i]);
}
alert(dataTest2); //This works here, but not if I move it outside of the method, even if I return it.
var testReturn = this.googleSpreadsheetKey; //trying to return any property using "this" - I've also tried this.googleSpreadsheetKey.value but still undefined
return testReturn; //returns "Undefined"
}
});
}
You could use Google Sheets webQuery. Basically, this is a method to export the Spreadsheet's data into a given format such as csv, json, etc. In your case, the link should look like this:
https://docs.google.com/spreadsheet/tq?key=12x66_QEkTKg_UzvpHEygdTmfnu7oH81pSQYn78Hxt80&gid=4&tq=select%20A,%20B&tqx=reqId:1;out:csv;%20responseHandler:webQuery
Please note that here "tg?key" is the key of your Google Sheet, and "&gid=" is NOT 4, this only tells Highcharts to selected Sheet 4, but for Google Sheets look at the source link and copy the numbers which go after "&gid=". Furthermore, "&tq=" is used to select the columns of the Google Sheet, which in the link above selects "Column A" and "Column B". To find out more on how to select columns and query the output refer to:
https://developers.google.com/chart/interactive/docs/querylanguage?csw=1#Setting_the_Query_in_the_Data_Source_URL
Lastly, "&tqx=" is used to output your data in the format you want. The above link uses "out:csv" which will output the data as comma-separated values. This could as well be Json if you like. Have a look at this documentation:
https://developers.google.com/chart/interactive/docs/dev/implementing_data_source#requestformat
In order to implement this output into your javascript code which you would then use to built your chart, you could use external Javascript libraries to handle these outputs. If you output your data as CSV, you can use "papaparse.js" to parse the CSV into Json which you can be then read by highcharts and allows you to built the chart. Refer to this documentation:
http://papaparse.com/docs#remote-files
An alternative to this would be, to output your Google Sheets directly as Json, then use jquery to make an Ajax Call and load the JSON-encoded data into your Javascript code. Precisely, you could perhaps use jQuery.getJSON() to get the data. Look at this link for more details on how to get Json:
http://api.jquery.com/jquery.getjson/
Finally, it is up to you on which format you choose to output the data, I prefer using Json as it saves you the extra step of having to convert the CSV into Json. Whatever suits you best and is easier for you to understand.
Once you have your data, you may have to parse your Json objects with Json.parse(), and then organize your data into an array with .push(). As #jlbriggs stated, organize your data first before you built the chart. Afterwards, you can make two, three or more Ajax calls to import data from different sources. I would not use many as this will impact in your loading and slow down data transfer.
NB: It is important to format the data accordingly for Highcharts to recognize the data, so use parseFloat() to convert strings into numbers, Date.UTC() to convert strings into date, etc.
Hope this helps you.
I am currently taking my first steps in D3 data visualisation. So far, the D3 tutorials have helped me a lot. The pie chart tutorial http://bl.ocks.org/mbostock/3887235 though does not further explain the necessary data structure for pie charts.
My data is more complex than the label/value structure of the example. I have the annual total import data and import data of a specific good stored in JSON:
var data = [{"year":"2001","total_import":"100000","import_specific_good":"25000"},{"year":"2002",...}];
If I understand the tutorial correctly pie() iterates over the SAME entry of each DIFFERENT object.
What if I need specific DIFFERENT values of the SAME object?
I am not interested in a pie showing all annual total imports as portions, but the annual import of a specific good as a portion of the annual total import. My values would be 1. (total_import - import_specific_good) and 2. import_specific_good.
Is my proposed data structure correct for what I want to do? Or do I have to restructure everything so that the values for every year are stored in a separate variable?
var data_2001 = [{"label":"Total Import","value":"100000"},{"label":"Import of Specific Good","value":"25000"}];
var data_2002 = [{"label": ...}];
You don't have to use a specific data structure -- you can (and will need to anyway) modify the example so you can use anything you like! So you can use your first JSON just fine. As you have only 2 values to show, you could simply construct the structure to pass to .data() on the fly.
// for pie chart
...data([json[index].total_import - json[index].import_specific_good,
json[index].import_specific_good])...
...
// similarly for the labels
I would advise to store the numbers as numbers (e.g. without quotes) in your JSON though -- otherwise you'll have to convert them to numbers in Javascript.