How to change calculation on nv3d when switching to stacked? - javascript

I'm using d3.js and nvd3.js to display some data from different datasets. One of the sets (A) contains the absolute number of orders, the other set (B) contains the number of orders from new customers, such that A >= B for every position. Example:
[{
key : 'orders',
values: [[1, 10], [2, 5], [3, 8], ...]
},{
key : 'orders by new customers',
values: [[1, 4], [2, 0], [3, 4], ...]
}]
I'd like to use a stacked multibar chart to display those series. In "Grouped" view, everything works nicely and I have both bars grouped beneath each other. However, when I switch to "Stacked" mode I was expecting, that the overall number does not change. It appeared that nv3d.js is then adding up both values and i get a new overall value.
Is there a way to change the calculation when switching to stacked mode? I was digging through the source code, but could not find a usable method to achieve this.
Thanks in advance!

If I understood your problem correctly, it would make more sense to restructure your data to make it conceptually match with bars being 'stacked' (which implies two values being added together), to something like this where:
orders = recurring orders + orders by new customers
[{
key : 'recurring orders',
values: [[0, 6], [0, 5], [0, 4], ...]
},{
key : 'orders by new customers',
values: [[1, 4], [2, 0], [3, 4], ...]
}]

Related

How to set individual layout properties for feature points with mapbox-gl?

I have an array of feature points, and wan't to update some layout properties on each feature point, individually. How to I do this?
This is what I have so far.
const features = getVisibleFeatures();
// This updates all. Not what I wan't. Each feature should have different offset.
map.setLayoutProperty("ports", "text-offset", [5, 5]);
Each feature should have it's own text-offset, based on individual values. How do I achieve this?
Update
#steve-bennett offers some great suggestion in the comments below, but unfortunately they don't work with layout properties and the text-offset values.
It's important that a solution can work with this.
After a lot of searching, trial and error, I figured out I could do this:
map.setLayoutProperty("ports", "text-offset", {
property: "id",
type: "categorical",
stops: [
["0", [2, 1]],
["1", [2, 0]],
["2", [0, 2]],
],
default: [0, 0],
});
"0", "1" and "2" is matched against the properties.id field. So I can do something like this:
map.setLayoutProperty("layout-id", "text-offset", {
property: "id",
type: "categorical",
stops: nodes.map((node) => {
const x = node.vx;
const y = node.vy;
return [node.id, [x, y]];
}),
default: [0, 0],
});

How to display an array of pair arrays as key values pairs?

I am writing a client in Ract that receives streaming data representing objects from a back end. The client parses this data and dynamically builds the object as a javascript data structure (typically an object or an array).
The backend has a Timeseries datatype that consists of timestamp keys and arbitrary values. A Timeseries can have duplicate timestamp keys like so:
{
'2019-08-22T18:34:15.777927965Z' : 1,
'2019-08-22T18:34:15.777927965Z' : 2,
'2019-08-22T18:34:15.777927965Z' : 3,
}
This means that I cannot use a javascript object to build this datastructure in the client given that only the last key/value pair added will be stored since the keys are the same.
My solution was to collect this data in an array:
[
['2019-08-22T18:34:15.777927965Z', 1],
['2019-08-22T18:34:15.777927965Z', 2],
['2019-08-22T18:34:15.777927965Z', 3],
]
The problem is that I have been asked to display this data in key/value format the way a javascript object would be displayed.
I am using the react-json-tree npm package to dislpay all the objects I am constructing which just takes an object or array and formats it nicely with collapsable dropdown arrows in the UI (this is not essential).
What options do I have to turn my array of arrays in the code into a nicely formatted object like data structure in the UI?
TLDR:
How do I display an array like this:
[
['2019-08-22T18:34:15.777927965Z', 1],
['2019-08-22T18:34:15.777927965Z', 2],
['2019-08-22T18:34:15.777927965Z', 3],
]
As colon separated key/value pairs in the UI, like objects?
Ideally I could pass this data structure into a library like react-json-tree.
You can display your data in the following way, if you want them to be given as a list :
const data = [
['2019-08-22T18:34:15.777927965Z', 1],
['2019-08-22T18:34:15.777927965Z', 2],
['2019-08-22T18:34:15.777927965Z', 3],
]
const Renderer = () =>
<ul>
{data.map(([key, val], id) => <li key={id}>{key}; {val}</li>)}
</ul>;
ReactDOM.render(<Renderer/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<div id="root"/>
To display it using react-json-tree, how about wrapping your array within an object ?
const data = [
['2019-08-22T18:34:15.777927965Z', 1],
['2019-08-22T18:34:15.777927965Z', 2],
['2019-08-22T18:34:15.777927965Z', 3],
]
<JSONTree data={{log: data}} />
OR
const data = {
log : [
['2019-08-22T18:34:15.777927965Z', 1],
['2019-08-22T18:34:15.777927965Z', 2],
['2019-08-22T18:34:15.777927965Z', 3],
]
}
<JSONTree data={log} />

how to transform changing data to be visualized in a chart.js

I am using a url to fetch data that constantly updates and changes. It comes back in the form of an array like this:
[[0,14],[1,11],[2,15],[3,12],[4,8],[5,8],[6,9],[7,9],[8,9],[9,7]].
I would like this to be transformed so I can use it in a chart.js
I think I should convert it to a json file, but don't really know how it works because the fetch needs to be initialized every 5 seconds and that new data has to be put in the json file every time and then displayed in the chart.js.
I got the data in the updatingArray[], but i'm stuck now.
function getDataFromDatapointsUrl(){
const proxyurl = "https://cors-anywhere.herokuapp.com/";
const url = 'https://canvasjs.com/services/data/datapoints.php)';
fetch(proxyurl + url)
.then(response => response.text())
.then(contents => createArrayForUpdatingData(contents));
}
getDataFromDatapointsUrl();
// setInterval(getDataFromDatapointsUrl, 500);
var updatingDataArray = [];
function createArrayForUpdatingData(updatingData){
updatingDataArray.push(updatingData);
}
I would like the data from the array to be split up in the chart.
[[0,14],[1,11],[2,15],[3,12],[4,8],[5,8],[6,9],[7,9],[8,9],[9,7]].
So the 0,1,2,3,4,5,6,... should become the x-axis and the 14,11,15, ... should become the value of the chart-line, bar-, pie, whatever you like it to visualized like.
Based on your example you can simply iterate updatingDataArray and push each value to a separate array that you then pass to Chart.js:
var updatingDataArray = [
[0, 14],
[1, 11],
[2, 15],
[3, 12],
[4, 8],
[5, 8],
[6, 9],
[7, 9],
[8, 9],
[9, 7]
];
var labels = [],
values = [];
updatingDataArray.forEach(function(val, idx) {
labels.push(val[0]);
values.push(val[1]);
});
new Chart(document.getElementById("chart"), {
type: "line",
data: {
labels: labels,
datasets: [{
data: values
}]
},
options: {}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<canvas id="chart"></canvas>

LoDash: How to remove null values and index of null values from two arrays with _.flow?

Problem
I have an array of arrays:
const multiple = [[1, 2, null, 7], [6, 8, 9, 1]]
Now I'd like to remove all null values and the corresponding element from the other array which results in:
[[1, 2, 7], [6, 8, 1]]
I'm able to do that but I'm looking for a solution with _.flow.
Approach
This is my approach that doesn't return an array of arrays and also doesn't remove the element from the other array.
_.flow([
xorWith(_.isNull)
])([1, 2, null, 7], [6, 8, 9, 1])
1. Update
My input will always be [[ // Elements], [ // Elements]]. It wasn't clear at my approach.
const multiple = [[1, 2, null, 7], [6, 8, 9, 1]];
const withoutNulls = (arr) => _.every(arr, _.negate(_.isNull));
const result = _.flow(
_.zip,
(tuples) => _.filter(tuples, withoutNulls),
_.unzip
)(...multiple)
console.log(result);
<script src="https://unpkg.com/lodash#4.17.5/lodash.js"></script>
Does that suit your needs, or you want it exactly with your functions set?
I can't get the basic idea of yours, because the flow function accepts functions and call them in chain, but it is not as in your case.
_.flow((...args) => _.map(args, arr => _.filter(arr, v => !_.isNull(v))), console.log)([1, 2, null, 7], [6, 8, 9, 1])
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.5/lodash.min.js"></script>

data parsing using a csv file in d3

consider the example shown in the link Labeling the axis with alphanumeric characters. Is this the correct way to parse var data?
var data = []
d3.csv("data.csv", function(data) {
data = data.forEach(function(d) { return [ x[d[0]], y[d[1]]] });
console.log(data)
});
data.csv should hold these values
[2, 2],
[3, 3],
[4, 4],
[5, 4],
[5.5, 5],
[6, 6],
[6, 7],
[6.5, 8],
[6.5, 16],
[17, 16]
Assuming that you meant that data should hold those values, your data.csv should look like the following:
first,second
2,2
3,3
4,4
5,4
5.5,5
6,6
6,7
6.5,8
6.5,16
17,16
And then you can parse it using the names of the fields:
var data = []
d3.csv("data.csv", function(csvData) {
// By default, all the values read are treated as strings.
// So have to make them numbers explicitly
data = csvData.forEach(function(d) { return [ +d.first, +d.second ] });
console.log(data);
// Draw the chart here.
});

Categories