It seems that machine learning via JavaScript is in it's infancy as there are hardly any libraries which fit each other calculation wise and visualization wise.
I am using figue.js library and wish to output the result via the following:
http://www.meccanismocomplesso.org/en/dendrogramma-d3-parte1/
http://www.meccanismocomplesso.org/en/dendrogramma-d3-parte2/
http://www.meccanismocomplesso.org/en/dendrogramma-d3-parte3/
This is what it requires:
{
"name": "root", "y" : 0,
"children": [
{
"name": "parent A", "y" : 30,
"children": [
{"name": "child A1", "y" : 100},
{"name": "child A2", "y" : 100},
{"name": "child A3", "y" : 100}
]
},{
"name": "parent B", "y" : 76,
"children": [
{"name": "child B1", "y" : 100},
{"name": "child B2", "y" : 100} // <--- number at the end is the ultrametric distance
]
}
]
}
This is what figue.js is giving me(of course it's different, all of the developers do this...):
{
"label": -1,
"left": {
"label": "Point 1",
"left": null,
"right": null,
"dist": 0,
"centroid": [
13.0406203,
55.606759100000005
],
"size": 1,
"depth": 0
},
"right": {
"label": -1,
"left": {
"label": -1,
"left": {
"label": -1,
"left": {
"label": "Point 2",
"left": null,
"right": null,
"dist": 0,
"centroid": [
13.0403852,
55.6066934
],
"size": 1,
"depth": 0
},
"right": {
"label": "Point 5",
"left": null,
"right": null,
"dist": 0,
"centroid": [
13.0404121,
55.6066418
],
"size": 1,
"depth": 0
},
"dist": 0.00005819080683319214,
"centroid": [
13.04039865,
55.606667599999994
],
"size": 2,
"depth": 1
},
"right": {
"label": "Point 3",
"left": null,
"right": null,
"dist": 0,
"centroid": [
13.0404818,
55.606629700000006
],
"size": 1,
"depth": 0
},
"dist": 0.00007074249076717127, // <--- ultrametric distance
"centroid": [
13.040426366666667,
55.60665496666667
],
"size": 3,
"depth": 2
},
"right": {
"label": "Point 4",
"left": null,
"right": null,
"dist": 0,
"centroid": [
13.0405408,
55.6066934
],
"size": 1,
"depth": 0
},
"dist": 0.00008682562985036432,
"centroid": [
13.040454975000001,
55.606664574999996
],
"size": 4,
"depth": 3
},
"dist": 0.00010313457228779574,
"centroid": [
13.040488040000003,
55.606683479999994
],
"size": 5,
"depth": 4
}
I can say that this is complicated to resolve. Or does anyone know of any libraries that may compile the structure?
var root = figue.figue.agglomerate(figueLabels, figueVectors, figue.figue.EUCLIDIAN_DISTANCE, figue.figue.SINGLE_LINKAGE);
// the above code is from figue.js, I have however modified the library so that it is module and works in nodejs
// the code below is the adapter
function recursive(json) {
var str;
if (json.left !== null || json.right !== null) {
str = {
name: '',
y: json.dist,
children: []
};
if (json.left !== null) {
str.children.push(recursive(json.left));
}
if (json.right !== null) {
str.children.push(recursive(json.right));
}
} else {
str = {
name: json.label,
y: json.dist
};
}
return str;
}
var json = recursive(root);
// there we go, now we can use the json variable as an argument for the visualization
console.log(JSON.stringify(json));
Below is the result!
Related
I'm looking for a way to filter this JSON and retrieve only the cost when fid > 10
Working example, the parent prop is an array:
[
{
"id": 1,
"properties": {
"parent": [
{
"fid": 10,
"cost": 100
}
]
}
},
{
"id": 2,
"properties": {
"parent": [
{
"fid": 20,
"cost": 200
}
]
}
},
{
"id": 32,
"properties": {
"parent": [
{
"fid": 30,
"cost": 300
}
]
}
}
]
JSONPath = $[*].properties.parent[?(#['fid']>10)].cost
result = [
200,
300
]
Not working example, the parent prop is now an object:
[
{
"id": 1,
"properties": {
"parent": {
"fid": 10,
"cost": 100
}
}
},
{
"id": 2,
"properties": {
"parent": {
"fid": 20,
"cost": 200
}
}
},
{
"id": 32,
"properties": {
"parent": {
"fid": 30,
"cost": 300
}
}
}
]
JSONPath = $[*].properties.parent[?(#['fid']>10)].cost
The result is No match
try this
$[?(#.properties.parent.fid>10)].properties.parent.cost
There can two sets of objects
First can be a straight forward where is no children
const noChildObj = [{
"id": 1,
"label": ["Description"],
"lines": 1,
"type": "string",
"precision": 2,
"width": 167.8
}, {
"id": 2,
"label": ["Information", "Ratio"],
"lines": 2,
"type": "number",
"precision": 2,
"width": 167.8
}, {
"id": 3,
"label": ["Tracking", "Error"],
"lines": 2,
"type": "number",
"precision": 2,
"width": 167.8
}]
So,in this case, there is no child , so property 'width' is at the topmost layer.
Second is where nesting of objects occur
So each object in the array will have a child object
[{
"id": "257",
"label": [""],
"lines": 1,
"children": [{
"id": "Description",
"label": ["Dates"],
"lines": 1,
"type": "date",
"precision": null,
"width": 839
}]
}, {
"id": "258",
"label": ["Cumulative Return"],
"lines": 1,
"children": [{
"id": 12,
"label": ["Russell 1000 Value - Price Return"],
"lines": 1,
"type": "number",
"precision": 2,
"width": 839
}]
}]
Here each object has a child object where the property width exists
This nesting is not limited to just 1 level
It can go upto 4 levels
So my use case requires if the innermost child has width undefined or not
I do realise that through recursion , we can traverse and find out..
But is there any function which can do it in less lines of code..may be in lodash
Please help
Know only how to do with recursion:
const objArray = [{
"id": 1,
"label": ["Description"],
"lines": 1,
"type": "string",
"precision": 2,
"width": 167.8
}, {
"id": "257",
"label": [""],
"lines": 1,
"children": [{
"id": "Description",
"label": ["Dates"],
"lines": 1,
"type": "date",
"precision": null,
"width": 839
}]
}]
const getWidthDeep = (el) => el.children && el.children[0]
? getWidthDeep(el.children[0])
: el.width
const result = objArray.map(getWidthDeep)
console.log(result)
I have created a Javascript array that I need to reformat into Json so that I can display it in a table.
I am trying to take the following javascript array:
[
{
"name": "ticker",
"value": "V"
},
{
"name": 5,
"value": -0.09453565931246788
},
{
"name": 10,
"value": -0.08185562540645996
},
{
"name": 90,
"value": -0.1023591207807445
},
{
"name": 120,
"value": -0.03745328055393815
},
{
"name": 250,
"value": 0.13101799630844946
}
]
And transform it into:
const myTableData = [
{"name": "ticker", "value": V},
{"name": "5", "value": -0.09453565931246788},
{"name": "10", "value": -0.08185562540645996},
{"name": "90", "value": -0.1023591207807445},
{"name": "120", "value": -0.03745328055393815},
{"name": "250", "value": 0.13101799630844946}
];
How can I do this?
Just use JSON.stringify
var myArray = [
{
"name": "ticker",
"value": "V"
},
{
"name": 5,
"value": -0.09453565931246788
},
{
"name": 10,
"value": -0.08185562540645996
},
{
"name": 90,
"value": -0.1023591207807445
},
{
"name": 120,
"value": -0.03745328055393815
},
{
"name": 250,
"value": 0.13101799630844946
}
];
var myJsonString = JSON.stringify(myArray);
console.log(myJsonString);
How to print this dynamically?
data = {
"name": "EU",
"size": 10,
"nodes": [
{
"name": "England",
"size": 2,
"nodes": [
{
"name": "Center",
"size": 1,
"nodes": [
{
"name": "main street",
"size": 0.5,
"nodes": []
}
]
},
{
"name": "Vilage",
"size": 1,
"nodes": []
}
]
},
{
"name": "Germany",
"size": 4,
"nodes": []
}
]
}
and I need somehow dynamically print it like this
EU 10
EU - England 2
EU - England - Center 1
EU - England - Center - main street 0.5
EU - England - Vilage 1
EU - Germany 4
This is the code that i have closest what I need
var data = { "name": "EU", "size": 10, "nodes": [ { "name": "England", "size": 2, "nodes": [ { "name": "Center", "size": 1, "nodes": [ { "name": "main street", "size": 0.5, "nodes": [] } ] }, { "name": "Vilage", "size": 1, "nodes": [] } ] }, { "name": "Germany", "size": 4, "nodes": [] } ] }
function printValues(obj) {
for (var key in obj) {
if (typeof obj[key] === "object") {
printValues(obj[key]);
} else {
console.log(obj[key]);
}
}
}
printValues(data)
This is what I get
You were on the right track - you can indeed use recursion to walk the data structure. What you also need is to get the name property and build up a the start of each line from each name encountered. You can ferry that information using a second parameter to the recursive function. Then you need to recursively call the function for each child node and pass all the names encountered so far:
const data = { "name": "EU", "size": 10, "nodes": [ { "name": "England", "size": 2, "nodes": [ { "name": "Center", "size": 1, "nodes": [ { "name": "main street", "size": 0.5, "nodes": [] } ] }, { "name": "Vilage", "size": 1, "nodes": [] } ] }, { "name": "Germany", "size": 4, "nodes": [] } ] }
function printValues(data, prefix = []) {
//make a copy of the prefix instead of mutating it
let location = prefix.concat(data.name);
console.log(location.join(" - "), data.size);
data.nodes.forEach(child => printValues(child, location))
}
printValues(data)
Here what i got
var data = { "name": "EU", "size": 10, "nodes": [ { "name": "England", "size": 2, "nodes": [ { "name": "Center", "size": 1, "nodes": [ { "name": "main street", "size": 0.5, "nodes": [] } ] }, { "name": "Vilage", "size": 1, "nodes": [] } ] }, { "name": "Germany", "size": 4, "nodes": [] } ] }
function printElem(str, element) {
ret = str + " " + element.name + " " + element.size;
console.log(ret);
for (item of element.nodes) {
printElem(str + " " + element.name, item);
}
}
printElem("", data);
Try this -
var data = { "name": "EU", "size": 10, "nodes": [ { "name": "England", "size": 2, "nodes": [ { "name": "Center", "size": 1, "nodes": [ { "name": "main street", "size": 0.5, "nodes": [] } ] }, { "name": "Vilage", "size": 1, "nodes": [] } ] }, { "name": "Germany", "size": 4, "nodes": [] } ] }
function printValues(data, prepend) {
console.log(prepend + data.name + ' ' + data.size);
prepend = prepend + data.name + ' - ';
for (node of data.nodes) {
printValues(node, prepend)
}
}
printValues(data, '')
You could take a closure over the visited names and iterate the nodes.
const
getItems = (parts = []) => ({ name, size, nodes = []}) => {
console.log(`${parts.concat(name).join(' - ')} ${size}`)
nodes.forEach(getItems(parts.concat(name)));
};
var data = { name: "EU", size: 10, nodes: [{ name: "England", size: 2, nodes: [{ name: "Center", size: 1, nodes: [{ name: "main street", size: 0.5, nodes: [] }] }, { name: "Vilage", size: 1, nodes: [] }] }, { name: "Germany", size: 4, nodes: [] }] };
getItems()(data);
One way is to use recursion on the nodes list:
I'm outputting the results with console.log.
Changed thanks to comment by VLAZ.
var data = { "name": "EU", "size": 10, "nodes": [ { "name": "England", "size": 2, "nodes": [ { "name": "Center", "size": 1, "nodes": [ { "name": "main street", "size": 0.5, "nodes": [] } ] }, { "name": "Vilage", "size": 1, "nodes": [] } ] }, { "name": "Germany", "size": 4, "nodes": [] } ] }
function printValues(prefix,obj) {
if (typeof obj !== "object") return;
prefix = prefix?(prefix+" - "+obj.name) : obj.name;
console.log(prefix+" "+obj.size);
for (var key in obj.nodes) {
printValues(prefix,obj.nodes[key]);
}
}
printValues("",data);
I have two variables array1 and array2 as following and I want to put the values of array2 into array1 for the properties present in array1 and rest of the properties should remain the same with default values.
One solution I have is to iterate through the array length and set values for found properties and but my array is too long to perform iteration (the array supplied in this question is just a raw value).
I need some better way other than iteration.
var array1=[
{
"name": "a",
"value": 0,
"level": [
{
"name": "a1",
"value": 0
},
{
"name": "a2",
"value": 0
}
]
},
{
"name": "b",
"value": 0,
"level": [
{
"name": "b1",
"value": 0
},
{
"name": "b2",
"value": 0
}
]
},
{
"name": "c",
"value": 0,
"level": [
{
"name": "c1",
"value": 0
},
{
"name": "c2",
"value": 0
}
]
}
]
var array2=[
{
"name": "a",
"value": 1,
"level": [
{
"name": "a1",
"value": 1
},
{
"name": "a2",
"value": 0
}
]
},
{
"name": "b",
"value": 1,
"level": [
{
"name": "b1",
"value": 0
},
{
"name": "b2",
"value": 1
}
]
}
]
and the required output is
var final_array=[
{
"name": "a",
"value": 1,
"level": [
{
"name": "a1",
"value": 1
},
{
"name": "a2",
"value": 0
}
]
},
{
"name": "b",
"value": 1,
"level": [
{
"name": "b1",
"value": 0
},
{
"name": "b2",
"value": 1
}
]
},
{
"name": "c",
"value": 0,
"level": [
{
"name": "c1",
"value": 0
},
{
"name": "c2",
"value": 0
}
]
}
]
A recursive solution with two iterators, one for arrays iterateA and one for objects iterateO. This proposal uses the thisArg for reference to json2.
Basically both callbacks iterates over the items or keys and checks if this is set and if the actual item is present in this. if not, the function returns.
The rest is straight forward, if an object is found, then it iterates over the keys and the object, if an array is found, the it it iterates over the array.
Only in the case of k === 'value' the value of this[k] is to o[k] assigned.
var json1 = [{ "name": "a", "value": 0, "level": [{ "name": "a1", "value": 0 }, { "name": "a2", "value": 0 }] }, { "name": "b", "value": 0, "level": [{ "name": "b1", "value": 0 }, { "name": "b2", "value": 0 }] }, { "name": "c", "value": 0, "level": [{ "name": "c1", "value": 0 }, { "name": "c2", "value": 0 }] }],
json2 = [{ "name": "a", "value": 1, "level": [{ "name": "a1", "value": 1 }, { "name": "a2", "value": 0 }] }, { "name": "b", "value": 1, "level": [{ "name": "b1", "value": 0 }, { "name": "b2", "value": 1 }] }];
function iterateO(o) {
return function (k) {
if (!this || !(k in this)) {
return;
}
if (typeof o[k] === 'object') {
Object.keys(o[k]).forEach(iterateO(o[k]), this[k]);
return;
}
if (Array.isArray(o[k])) {
o[k].forEach(iterateA, this[k]);
return;
}
if (k === 'value') {
o[k] = this[k];
}
};
}
function iterateA(a, i, aa) {
if (!this || !(i in this)) {
return;
}
if (typeof a === 'object') {
Object.keys(a).forEach(iterateO(a), this[i]);
return;
}
if (Array.isArray(a)) {
a.forEach(iterateA, this[i]);
return;
}
}
json1.forEach(iterateA, json2);
document.write('<pre>' + JSON.stringify(json1, 0, 4) + '</pre>');