How to use D3.js to draw this graph - d3.js

I saw a graph that can efficently perform the relations between caller and callee(the functions that are called).The tree-like diagram is much clear for us to know the calling frequency and hierarchy.
... I know how to use D3 to draw a "Indented Tree" but don't know how to draw that tree.
I have some json data that contain "name"/"child"/"caller name"/,and "child" is a list contains all children.
"name": "eval",
"caller": "__main__",
"children": [
{
"name": "zend_compile_string",
"caller": "eval",
"children": [],
"call_num": 1,
"all_index": "[17]"
}
I sincerely want to know how to draw a line between parent and child node in this graph? one line links one parent and one child, and the parent node is at the upper level and the child node is at the lower level.
Thanks!!!!!

Related

Handling Category Collisions

Fiddle: https://jsfiddle.net/h7zf55b0/
I have a graph I am trying to design with the given data. The problem is I am getting category collision as its possible that multiple data points have the same date (which I use as the category axis).
{
'data': "18.46",
'date': "2015-12-31T09:36:00.0000000Z",
'type': "bid"
},
{
'data': "40.3918",
'date': "2015-12-31T09:36:00.0000000Z",
'type': "ask"
},
amcharts is handling this by drawing the columns over each other as shown in the fiddle.
Is there a way to make amcharts put these columns next to each other? Or stack them?
Ideally I want to be able to specify 'type' as a grouped element or something, so that the columns are labeled "40.3918 ASK 9:36am"
On date-based category axis, the chart tries to retain natural time scale. So if you have several columns on the same category, it draws them over each other.
You can disable this functionality by setting equalSpacing: true in your categoryAxis.
This way the chart rather than putting columns where they are supposed to be in time, will put each data point consecutively, regardless of the order and distance in time between them.
"categoryAxis": {
"gridPosition": "start",
"parseDates": true,
"equalSpacing": true,
"minPeriod": '60ss',
"axisAlpha": 0,
"gridAlpha": 0,
"position": "left"
}
As for what is shown in the balloons, you can use balloonText or, if you need some very custom functionality to generate balloon data balloonFunction.
Another option would be to combine those data points into same-category data points, as well as define a graph for each type:
https://jsfiddle.net/h7zf55b0/1/

crossfilter and dc.js line chart to plot every data point in ascending/descending order

My data consists of simple information for contracts. Simplified each one looks like this:
{
"id": 1234567890,
"district": "districtname",
"city": "cityname",
"test": "testnumber",
"date": "2015-03-15",
"score": 0.0 - 1.0
}
I already have a simple dc.barChart for the number of tests per day and a dc.rowChart for districts and another one for cities to filter the currently displayed data with crossfilter.
What I need now is a line chart that plots every score of every contract in ascending or descending order. By that I mean that I do not want to group the data by score but simply plot every score on the y-axis and have nothing on the x-axis. Assuming data is plotted in ascending order the resulting picture will be an ever increasing graph. See below:
How do I do this with data that lives inside a crossfilter instance, dc.js and d3.js?

d3.js force layout - filter and restoring nodes by attribute

I have been struggling with this issue for a long time with very little progress. I was going to put my code up here but it becomes quite long and convoluted and I'm still not sure I am even taking the correct approach so I thought backing up, showing the data and saying what I want to accomplish would be a approach to take.
Basically my goal is to create a d3 force layout. All data will be 'hard coded' into the page. I have done some network analysis on the nodes and have included those metrics in the dataset (eigenvector, betweeness, etc.) I want to be able to create the network vis, and have sliders that I can use to filter the network down by the various metrics. In other words I have a range slider that is set to the min and max of the network's “degree” metric (as an example) and as I adjust the slider values the network filters the nodes that fall outside those values. I want to be able to filter these nodes out and back in.
I've seen a number of examples of filtering and most are concerned with reducing the network and don't speak to the restoring the nodes. My attempts have resulted in either nothing happening, or multiple copies of existing nodes being created, or any number of behaviors, but not what I'm after. There is so many ways to 'skin the cat' in d3 that I keep going down paths that don't allow me (or I'm just not able to understand) to control the filtering the way I want.
I don't want to just control the visibility, I want the nodes to be removed and restored completely, and for the network to readjust smoothly.
Here is a sample of the data that I am using ...
var dataset = {
“directed”: false,
“graph”: [],
“nodes”: [
{
“category”: “new”,
“eigen”: 0.05923,
“between”: 0.0,
“close”: 0.25265,
“deg”: 1,
“id”: “Name1”,
“uid”: 100006190145565
},
{
“category”: “known”,
“eigen”: 0.00411,
“between”: 0.002002792177543483,
“close”: 0.19151,
“deg”: 3,
“id”: “Name2”,
“uid”: 100002598631097
},
{
“category”: “new”,
“eigen”: 0.0,
“between”: 0.0,
“close”: 0.06203,
“deg”: 1,
“id”: “Name3”,
“uid”: 727631862
},
{
“category”: “new”,
“eigen”: 0.00725,
“between”: 0.0,
“close”: 0.21037,
“deg”: 1,
“id”: “Name4”,
“uid”: 100008585823128
},
],
“links”: [
{
“source”: 0,
“target”: 1
},
{
“source”: 0,
“target”: 1
},
{
“source”: 0,
“target”: 3
}
],
“multigraph”: false
};
I can supply some of my code as well, but I think it would simply muddy the discussion as I have tried multiple approaches, none of which worked well, each of which just seemed to confuse me further when I would achieve partial results. Any help you can provide would be greatly appreciated.

Visualize data count in d3

I want to visualize data count in d3. I have a dataset similar to this:
[
{
"name": "Team blue",
"color": "#0433ff"
"count": 9
},
{
"name": "Team red",
"color": "#ff2600"
"count": 12
}
]
and I want to visualize it like this: http://i.imgur.com/xjFeNYd.png
I understand the basics of data and enter() but I do not know which is the best way to create the red or blue boxes based on the count value.
Any help will be appreciated.
You can d3.range(number) to generate a range of numbers from 1 to number. You can then combine this with nested selections. The code looks like this:
block.selectAll("span")
.data(function(d) { return d3.range(d.count); })
.enter()
.append('span')
Complete demo (with fixed CSS) here. The way of getting the color for the span elements is a bit hacky at the moment as it indexes into the top-level data set. A cleaner way would be to make this data part of the elements generated with d3.range() and is left as an exercise for the reader.

Process multiple polygons d3

The answer below on drawing a polygon works well for a single polygon. However, what if there are more than one polygon? Simply adding an additional polygon with points seems not to work even though using "select all" would seem to indicate that it would be OK to add a couple more polygons without much problem..
We have an array of polygons, each of which has an attribute Points which is an array of points.
The first array with polygon should obviously be mapped and the point arrays of each member processed as described. But how to spedify this two-level structure with d3?
Proper format for drawing polygon data in D3
The answer is simple and straightaway. Just pass the array of polygons as data to d3 selection.
In your case it seems that you are using an array of polygons which are composite objects, each having a key called 'Points'. I assume it looks something like this-
var arrayOfPolygons = [{
"name": "polygon 1",
"points":[
{"x":0.0, "y":25.0},
{"x":8.5,"y":23.4},
{"x":13.0,"y":21.0},
{"x":19.0,"y":15.5}
]
},
{
"name": "polygon 2",
"points":[
{"x":0.0, "y":50.0},
{"x":15.5,"y":23.4},
{"x":18.0,"y":30.0},
{"x":20.0,"y":16.5}
]
},
... etc.
];
You will just have to use d.Points instead of d when writing the equivalent map function, which can be written as follows-
vis.selectAll("polygon")
.data(arrayOfPolygons)
.enter().append("polygon")
.attr("points",function(d) {
return d.points.map(function(d) {
return [scaleX(d.x),scale(d.y)].join(",");
}).join(" ");
})
.attr("stroke","black")
.attr("stroke-width",2);
You can check the following working JSFiddle to verify.
EDIT- The same example as above with convex hull implementation for rendering complete polygons. http://jsfiddle.net/arunkjn/EpBCH/1/ Note the difference in polygon#4

Resources