Is there a limitation on the "array" method, specifically an amount of data points required to have it work?
I was using it to display large volumes of data just fine, but when I lowered the amount of points I was plotting, it seemed to break, and only plot one point, with an incorrect X value.
When I switched to use the object notation for data points ({ x: new Date(), y: 100 }) it worked just fine.
To clarify, the two notations seem to function differently with different amounts of data. The only thing different between the below example and my production code are the actual dates/values. Syntax is the same.
[[Date.parse(i1), 100], [Date.parse(i2), 100]]
[{ x: Date.parse(i1), y: 100 }, { x: Date.parse(i2), y: 100 }]
http://api.highcharts.com/highcharts#series.data
The difference, as far as I can say, is that in the array notation, the Date object is not properly interpreted.
Using actual time stamps, both notations work the same.
Neither method should be affected by too few data points.
example:
http://jsfiddle.net/jlbriggs/yPLVP/148/
Related
I'm working on an application where datasets have programmatically generated names and are frequently created and destroyed by users. I want to graph these datasets within the application using D3.js.
My datasets are stored like this:
Wavelength
Transducer Output 1
Transducer Output 2
Transducer Output 3
1
19
21
23
3
23
20
21
5
33
23
19
7
33
24
45
etc..
etc..
etc..
etc..
Where wavelength should be mapped along the x axis, and magnitude mapped along the y axis, with an individual line for each set of magnitudes.
I'm struggling to get my head around how one should pass such data into D3.js. Each tutorial I read uses different data formats and different code. I have read the documentation, but it hasn't helped me much in learning how to format my data for D3 either.
What's the correct way to map these datasets onto a graph from within a script? At the moment I'm trying to use d3.csvParse(data), but am unsure where to go from there. I suspect I may be formatting my data awkwardly but am not sure.
Writing up a quick answer to this just incase anyone else gets stuck where I did. Essentially I completely misunderstood how you're supposed to present data to in d3.
Here's a useful guide to understanding d3 data handling
Here's a useful guide on how to use that data once you have it structured correctly
Once I realised that I needed to create an array which represented every point I want drawn things got a lot easier. I created an object with three properties that described a single data point.
Each object has a wavelength, magnitude, and a name.
wavelength is the datapoint's position on the x axis, magnitude is its position on the y axis, and name allows me to differentiate between the different datasets.
let array = [
{name: "dataset 1", wavelength: 2, magnitude: 20}
{name: "dataset 1", wavelength: 3, magnitude: 22}
{name: "dataset 1", wavelength: 4, magnitude: 19}
{name: "dataset 2", wavelength: 2, magnitude: 14} //and so on...
]
From there I could map that onto my graph with
svg.append("path")
.data(array)
.attr("d", d3.line()
.x(function(d) {return x(d.wavelength)})
.y(function(d) {return y(d.magnitude)})
.z(function(d) {return z(d.name)});
You can also group the data by name using d3.group() and iterate through that through your data manually, drawing each line individually
Thanks #Alexander Nied and #Gerardo Furtado for nudging me back on track!
The data I am trying to plot is of the form :
[
[24894174208.0, 1604842800],
[24903880704.0, 1604843100]
]
where x = data points; y = UNIX_EPOC_Time
while plotting I am interchanging x,y; so as to plot UNIX_EPOC_Time on X-axis & data points on Y-axis
I have to multiply UNIX_EPOC_Time by 1000 as: Javascript uses milliseconds internally, while normal UNIX timestamps are usually in seconds. ( Why do I need to multiply unix timestamps by 1000 in JavaScript? )
Also I am trying to find anomalies in the dataPoints which is being plotted with a dot (yellow/orange/red).
However, in the function
js[isIn(anomoly, point){...}]
where I find anomalies in dataPoints, I see the datapoints take the form as:
[1604923500000, 22179459072000]
instead of:
[1604923500, 22179459072.0]
due to which I have to divide the data point (here: 22179459072000) by 1000 to bring it to it's original form 22179459072.0 in order to plot it on the graph.
I am not sure why this is happening though.
I have reproduced the issue in stackblitz.
After some debugging, I finally found the source of the problem.
It is happening because of the way you are cloning your data.
let clone_element = { ...element };
The spread operator is not creating a deep copy of the element, it's just the shallow one meaning that some parts of the clone_element will still have a reference to the source of data causing mutation.
To fix that you could use for example the lodash's cloneDeep(). This function will produce a real deep copy, so there is no way you will mutate your initial data.
const clone_element = cloneDeep(element);
Live demo:
https://stackblitz.com/edit/highchart-highstock-pddlto?file=src%2Fapp%2Fapp.component.ts
Additional references:
What is the most efficient way to deep clone an object in JavaScript?
https://dassur.ma/things/deep-copy/
https://lodash.com/docs/4.17.15#cloneDeep
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
}
},
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
In highcharts if there are two series, where the first series value is 20,0000 and the second series value is 20, then the second series becomes so small that it is almost invisible.
Is it possible to break the first bar so that second series become visible? Below is the desired output...
At this time there is not a way to do this.
See the HighCharts User Voice here.
I have used a mathematic calculation in the past to solve this kinds of problems. Here is a couple of different examples:
VALUES: 220, 110, 55, 5
Normal Format
Square Root Format
VALUES: 1100, 220, 110, 55, 5
Normal Format
Square Root Format
What I do in the above examples to get low value series to show more is use the square root of all values. The data is sent as the square root rounded to the third decimal. Then I use the formatter on the yAxis label and tooltip to display the proper values.
Also, in the above examples, I am using whole numbers. When formatting the yAxis label and tooltip I am adding 1 and forcing them to an integer to get them back to the original needed number. This works great for whole numbers. If your data is not a whole number, then you would have to pass the entire result from the square root. Then of course not force it to an int.