As mentioned above i'm trying out the plot a chart using d3 where in i'd require the data to be in Parent Child relationship but i couldn't figure it out how to convert the MySQL query result to JSON parent child format.
Help provided will be very thankful.
I'm trying to replicate the chart in the below URL :
Zoomable Partition Layout (click on the partitions to zoom up or down the tree)
Data in MySQL :
Column1 Column2 Column3
First Top - 1500
First Child First Top 500
Second Child First Top 500
Third Child First Top 500
First Sub-Child First Child 250
First Sub-Child First Child 250
Second Sub-Child Second Child 250
Second Sub-Child Second Child 250
Third Sub-Child Third Child 250
Third Sub-Child Third Child 250
Desired Data Format :
{
"name": "First Top",
"children": [
{
"name": "First Child",
"children": [
{"name": "First Sub-Child", "size": 250},
{"name": "First Sub-Child", "size": 250}
]
},
{
"name": "Second Child",
"children": [
{"name": "Second Sub-Child", "size": 250},
{"name": "Second Sub-Child", "size": 250}
]
},
{
"name": "Third Child",
"children": [
{"name": "Third Sub-Child", "size": 250},
{"name": "Third Sub-Child", "size": 250}
]
}
]
}
Here's some pseudo-code, assuming one level of hierarchy:
get the parent/child rows from the database (select t1.parent, t1.item, size from tree t1, tree t2 where t1.parent=t2.item)
loop through the rows:
if parent is different than previous parent and previous parent is set:
push object onto array
start a new object
add child and size to object
push last object onto array
get root object (where parent is null)
encode object as json with root object; see Create JSON-object the correct way
output json
Related
Got a question regarding AngularJS and a carousel menu. I've made an array and I have trouble inserting the data in my View.
Controller:
gameApp.controller('homeController', function($scope) {
// Gamemodelist is static. Put all the corresponding gamemodes in an array
$scope.gameModeList = [
{"name": "Waterworld", "contents": [
{"name": "Classic", "contents": [
{"name": "Level 1", "contents": [{"name": "beginner"}, {"name": "easy"},{"name": "intermediate"}, {"name": "ultimate"}]},
{"name": "Level 2", "contents": [{"name": "easy"}]}
]},
{"name": "Firemode", "contents": [
{"name": "Level 3", "contents": [{"name": "beginner"}]}
]},
{"name": "Watermode", "contents":[
{"name": "Level 4", "contents": [{"name": "introduction"}]}
]}
]},
{"name": "Fireworld", "contents": [
{"name": "Classic", "contents": [
{"name": "Level 1", "contents": [{"name": "Intro"}, {"name": "Beginner"}, {"name": "Intermediate"}]},
{"name": "Level 2", "contents": [{"name": "Beginner"}, {"name":"Intermediate"}]}
]},
{"name": "Fireworld", "contents": [
{"name": "Level 3", "contents": [{"name": "Beginner"}, {"name": "Intermediate"}]}
]}
]},
{"name": "Tutorial", "contents": [
{"name": "Basic Tutorial"}, {"name": "Battle Training"}
]}];
}
This array is basicly the menu itself. You see the first items in the array are the first items in the menu. And every array in the contents is the submenu and if there is a subsubmenu.
This is my controller. Now I'm new to Angular, and I've already mate routing and templating work. Got different controllers for the login screen and the options screen. But now I'm working on the homescreen, which features a menu and I'm quite uncertain what's my best step here. I've already decided that I don't want to use different pages like I'm doing with my login and options screen, because I feel that an array is more convenient, because it already features the ordering of the items and it's (imo) a bit more managable.
To the view then. I've already checked and I think I need to use ng-if to check if there are submenu's in the array and if so use ng-repeat to display the menu. But. I come from jQuery background, so my instinct was to display the list and make it work with CSS and jQuery to manipulate the DOM so the items are shown which I want them to show, I know (for sure) that thats how things work in Angular. I guess I need to check with the controller which items need to display?
<ul>
<li class="animate-repeat" ng-repeat="mode in gameModeList">
{{ mode.name }}
</li>
</ul>
Now I only get the first items in the list obviously. I guess I now have to get the contents of the item I click in the view?
Hello Stackoverflow -
I have been attempting to create a sunburst chart using the examples provided at:
http://bl.ocks.org/kerryrodden/7090426 I can successfully replicate this particular piece of artwork - however, I have tried to add a twist and been unsuccessful thus far. Essentially these lines of code are what I believe I need to work with:
var partition = d3.layout.partition()
.sort(null)
.size([2 * Math.PI, radius * radius])
.value(function(d) { return d.size; });
I have tried a number of different variations on the line:
.value(function(d) { return d.size; });
including attempting to change the values of each parent to be set to a predefined value that I send over in the JSON. Essentially I want the chart to reflect how I have the JSON:
{
"name": "root",
"children": [
{
"name": "a",
"size": 100,
"children": [
{
"name": "b",
"size": 50,
"children": [
{
"name": "c",
"size": 25
},
{
"name": "d",
"size": 15
},
{
"name": "e",
"size": 35,
"children" : [
{
"name": "f",
"size": 10
},
{
"name": "g",
"size": 5
}
]
}
]
}
]
}
]
}
As you might notice each parent object contain the sum total of its children as well as its own value (set as size) the total value of the top most parent (root) is 100 because (a) is 100 however if you look at (b) which is 50 and (e) which is 35 there is 15 missing which is included in (a)'s size. I don't even know if what I want to do is possible or some variation. If you plugin in the json above the chart will render, but if you look at f and g they represent 100% of e when in fact what I want is for them to represent only 42% because the rest of e is represented by its own value plus f and g - thanks for reading have a great day.
I cannot comment because of low rep, so I'll have to give an answer. About the f and g representing 100% together: For all I know, that is normal behavior for d3.
I think you should prep your JSON data to reflect all the parts that you want to be shown (if that sentence makes any sense at all).
What i basically want to say is: if you want f and g to represent only 42%, you need an extra element h which has a value of 20. I don't think D3 has a way of figuring that out itself. Since it is data driven, D3 can only visualize existing data.
EDIT:
After looking again, i would say that your data structure is not the way you would want it to be. I think you need something like this:
{
"name": "root",
"children": [
{
"name": "a",
"size": 100,
"children": [
{
"name": "b",
"size": 75,
"children": [
{
"name": "c",
"size": 25
},
{
"name": "d",
"size": 15
},
{
"name": "e",
"size": 35,
"children" : [
{
"name": "f",
"size": 10
},
{
"name": "g",
"size": 5
},
{
"name": "h",
"size": 20
}
]
}
]
},
{
"name":"i",
"size":25
}
]
}
]
}
I have added element 'i' with value 25 so it completes element 'a' as following: a = b + i. You said that the value of the children ads up to be the value of the parent, but in the case of b, which seems to have 3 children, i came to the value 75 (25 + 15 + 35), so I changed the value of b and I added element 'i' with value 25 to get to the 100 of element a. D3 will pick up element 'i' and visualize it in the sunburst, just like element 'h'.
And like I said before the edit, I have also added element h, with value 20.
I have a hierarchical structure data, and can be treat as a tree structure.
First
I need to split this hierarchical tree into sub-tree and get all the sub-trees.
The function below is how I did, it works well
var hierarchObjects = [];
traverseNodes(root);
function traverseNodes(root){
hierarchObjects.push(root);
for(var i=0; i<root.children.length; ++i)
{
traverseNodes(root.children[i]);
}
}
Second
I need to group the nodes for each level of a subtree, in Array hierarchObjects. And the depth of the sub-tree is different.
For example,
put nodes of a sub-tree of level1 in array Level1.
put nodes of a sub-tree of level2 in array Level2.
So What should I do for Second process?
Is there a more efficient way for all the process?
Because My dataset is a bit big, and there are about 1300 sub-trees, I need to find an efficient way?
My dataset is a tree structure: http://www.csee.umbc.edu/~yongnan/untitled/pathwayHierarchy.json
You can see it is a parent-----children structure tree.
For this tree I use step 1 to split into sub-trees.
For each sub-tree, example as below:
1
{
"dbId": "111461",
"name": "Cytochrome c-mediated apoptotic response",
"children": [
{
"dbId": "111458",
"name": "Formation of apoptosome",
"children": [],
"size": 1
},
{
"dbId": "111459",
"name": "Activation of caspases through apoptosome-mediated cleavage",
"children": [],
"size": 1
}
]
}
for this sub-tree, it just has two children for level1, so the return array should be [[Formation of apoptosome,Activation of caspases through apoptosome-mediated cleavage ]]
2
{
"dbId": "111471",
"name": "Apoptotic factor-mediated response",
"children": [
{
"dbId": "111461",
"name": "Cytochrome c-mediated apoptotic response",
"children": [
{
"dbId": "111458",
"name": "Formation of apoptosome",
"children": [],
"size": 1
},
{
"dbId": "111459",
"name": "Activation of caspases through apoptosome-mediated cleavage",
"children": [],
"size": 1
}
]
},
{
"dbId": "111469",
"name": "SMAC-mediated apoptotic response",
"children": [
{
"dbId": "111463",
"name": "SMAC binds to IAPs ",
"children": [],
"size": 1
},
{
"dbId": "111464",
"name": "SMAC-mediated dissociation of IAPcaspase complexes ",
"children": [],
"size": 1
}
]
}
]
}
for this dataset, the result could be
[
[Cytochrome c-mediated apoptotic response,SMAC-mediated apoptotic response],
[Formation of apoptosome,Activation of caspases through apoptosome-mediated cleavage,SMAC binds to IAPs, SMAC-mediated dissociation of IAPcaspase complexes]
]
Now, I am trying to use Breadth first algorithm to do the Second step. I know the efficient is not very good.
Thanks!
This should do the trick, and unless you are handling around 1m nodes or very deep trees, should be pretty fast:
var data={
//your data
}
var arr=[]; // array that holds an array of names for each sublevel
function traverse(data, level){
if(arr[level]==undefined) arr[level]=[]; // if its the first time reaching this sub-level, create array
arr[level].push(data.name); // push the name in the sub-level array
for(var index=0;index<data.children.length;index++){ // for each node in children
traverse(data.children[index], level+1); // travel the node, increasing the current sub-level
}
}
traverse(data, 0); // start recursive function
console.log(arr)
Full fiddle: http://jsfiddle.net/juvian/fmhrpdbf/1/
I am new to D3, so my project of D3 is a rough problem to me and I really do need some help, I have been search solutions for days.
The problem is, I want to draw a Hierarchical Bar Chart, every time one clicks a bar, the sub layout of that bar is shown, just like this one http://bl.ocks.org/mbostock/1283663, however, the value of parent node is the sum value of its children node. I want to set the parent value by myself and keep the layout. The json file is:
{
"name": "flare",
"children": [
{
"name": "analytics",
"children": [
{
"name": "cluster",
"children": [
{"name": "AgglomerativeCluster", "size": 3938},
{"name": "CommunityStructure", "size": 3812},
{"name": "HierarchicalCluster", "size": 6714},
{"name": "MergeEdge", "size": 743}
]
},
I want to edit the parent value, so I edit the file as :
{
"name": "flare",
"children": [
{
"name": "analytics",size:555555 //I want to set value by myself rather than the sum of children value
"children": [
{
"name": "cluster",
"children": [
{"name": "AgglomerativeCluster", "size": 3938},
{"name": "CommunityStructure", "size": 3812},
{"name": "HierarchicalCluster", "size": 6714},
{"name": "MergeEdge", "size": 743}
]
},
However, it does not work. Does anyone knows how to set parent's value? I searched for days and got nothing, hope you can help me, and I am appreciate your help!
Is your issue with using the parent element sizes to draw the bars? If so, you should scale everything (to say 0 to 100) and then multiply this by a constant to get the appropriate parent value. After all, if you edit each parent value, they won't necessarily be proportional.
Here's an example of a scale:
edit: (fixed the domain)
var myscale = d3.scale.linear()
.domain([0, maxParentWidth])
.range([0,y]); // .range([0,1]) is the default range
This will scale all the "parents" on the domain 0 to the largest parent value to a range of [0,y], where y is whatever you want (i.e., 100). Let's say you want the largest parent bar to be 300px. Now, all you have to do is multiply this scaled value by a constant, in this case, 3.
http://bl.ocks.org/mbostock/4339083 am using this
instead of d3.json("/d/4063550/flare.json", function(error, flare) {
how do i make it use the json file within the html, like say i have
var jsonData = [{
"name": "A",
"children": [
{"name": "A1", "children": [{"name": "A12"},{"name": "A13"},{"name": "A14"}] },
{"name": "A2", "children": [{"name": "A22"},{"name": "A23"},{"name": "A24"}] }
]
}];
and i want to use this instead of an external json file, how do i achieve this ?
Solution:
1.you can assign the JSON data to variable name then You can build the tree layout
2.use one function to get the JSON data
Fiddle for 1 solution
Fiddle for 2 solution
var root = getData(),
nodes = cluster.nodes(root),
links = cluster.links(nodes);