I am trying to create pie charts using d3js. I dont face any issues when i used simple json file. But later when i tried to use slightly more complex json, i am getting these 2 errors.
Error: Problem parsing d="M0,-300A300,300 0 1,1 NaN,NaNLNaN,NaNA20,20 0 1,0 0,-20Z"
Error: Problem parsing d="MNaN,NaNA300,300 0 1,1 NaN,NaNLNaN,NaNA20,20 0 1,0 NaN,NaNZ"
from my understanding the error is at arcs.append("path").attr("d", arc). but donno how to fix it.
here is the d3js code
<div id="sample1">
<script>
var r = 300;
var color = d3.scale.category10()
var canvas = d3.select("#sample1").append("svg")
.attr("width", 700)
.attr("height", 700);
var group = canvas.append("g")
.attr("transform", "translate(350,350)");
var arc = d3.svg.arc()
.innerRadius(20)
.outerRadius(r);
var pie = d3.layout.pie()
.value(function(d) {
d.children.forEach(function(x) {
return x.value;
});
})
.sort(null);
d3.json("js/mydata.json", function(data) {
var arcs = group.selectAll(".arc")
.data(pie(data.children))
.enter()
.append("g")
.attr("class", "arc");
arcs.append("path")
.attr("d", arc)
.attr("fill", function(d) {
d.data.children.forEach(function(x) {
return color(x.name);
});
});
})
</script>
</div>
here is my json
{
"name": "All",
"children": [
{
"name": "Main1",
"children": [
{
"name": "Sub1",
"value": 6.25
},
{
"name": "Sub2",
"value": 12.50
},
{
"name": "Sub3",
"value": 6.25
}
]
},
{
"name": "Main2",
"children": [
{
"name": "Sub4",
"value": 6.25
},
{
"name": "Sub5",
"value": 12.50
},
{
"name": "Sub6",
"value": 6.25
}
]
},
{
"name": "Main3",
"children": [
{
"name": "Sub7",
"value": 6.25
},
{
"name": "Sub8",
"value": 12.50
},
{
"name": "Sub9",
"value": 6.25
}
]
},
{
"name": "Main4",
"children": [
{
"name": "Sub10",
"value": 6.25
},
{
"name": "Sub11",
"value": 12.50
},
{
"name": "Sub12",
"value": 6.25
}
]
}
]
}
Updated:
The approach given by "Lars Kotthoff" worked. how ever this approach does not fix my actual problem which i dint mentioned here. The problem is, i want to give a border to all the Main1,Main2,Main3,Main4. it means although there are 12 colors here borders will be only 4 i.e grouping all three colors into one based on ite parent.
Below picture shows my requirement.
Related
Using rotated labels on category X axis. (Real graph uses long names but results are the same.)
A: Alignment of axis labels and their data points is fine without label rotation.
B: Labels are not aligned when rotated.
The only difference between A and B graph coding is the addition of "labels":{"rotation":90} in the xAxes renderer.
How can alignment be fixed?
var chart =am4core.createFromConfig({
"colors": { "list": ["#DB3", "#000", "#888"] },
"data": [$data],
"legend": { "markers":{"width":20, "height":10},
"position":"top",
"useDefaultMarker":true
},
"series": [
{ "dataFields": { "categoryX":"X", "valueY":"Y1" },
"name": "[font-size:16px;font-weight:600;]{$n1}[/]",
"strokeWidth": 2,
"type": "LineSeries"
},
{ "dataFields": { "categoryX":"X", "valueY":"Y2" },
"name": "[font-size:16px;font-weight:600;]{$n2}[/]",
"strokeWidth": 2,
"type": "LineSeries"
},
{ "dataFields": { "categoryX":"X", "valueY":"Y3" },
"name": "[font-size:16px;font-weight:600;]others[/]",
"strokeWidth": 2,
"type": "LineSeries"
}
],
"xAxes": [
{ "dataFields": { "category": "X" },
"renderer": { "minGridDistance":11, "labels":{"rotation":90}},
"type": "CategoryAxis"
}
],
"yAxes": [
{ "renderer": {"minGridDistance":15},
"title": {"text": "[font-size:16px;font-weight:600;]Values[/]"},
"type": "ValueAxis"
}]
}, "line", am4charts.XYChart);
LABELS renderer needed "verticalCenter":"middle" with rotation.
I don't know how many other things I tried!
I am trying to understand the right usage to achieve my collapsible tree d3 but unable to establish the proper parent/child references since I cannot use "parent". Attempting to use parentID.
This is my dataset I am testing with:
var result = [
{ "id": 1, "name": "Top Level", "parent": null, "parentId": "" },
{ "id": 2, "name": "PROD", "parent": "Top Level", "parentId": 1 },
{ "id": 3, "name": "QAT", "parent": "Top Level", "parentId": 1 },
{ "id": 4, "name": "App1", "parent": "PROD", "parentId": 2 },
{ "id": 5, "name": "App1", "parent": "QAT", "parentId": 3 },
{ "id": 6, "name": "ServerPROD001", "parent": "App1", "parentId": 4 },
{ "id": 7, "name": "ServerQAT001", "parent": "App1", "parentId": 5 }
];
and based on the collapsible tree:
// convert the flat data into a hierarchy
var treeData = d3.stratify()
.id(function (d) { return d.name; })
.parentId(function (d) { return d.parent })
(result);
This works fine if I do not include items 6 and 7. If I do include these I get an ambiguity error which makes sense because it cannot determine which "App1" to associate to.
I tried changing the code to use the parentId but just get an error of "missing:1" now.
// convert the flat data into a hierarchy
var treeData = d3.stratify()
.id(function (d) { return d.name; })
.parentId(function (d) { return d.parentId })
(result);
Note - I cannot change the "App1" name values to something unique as they will exist in multiple areas with that given name.
Since you have the id that is unique and not the name:
// convert the flat data into a hierarchy
var treeData = d3.stratify()
.id(function (d) { return d.id; }) // return the id instead of the name
.parentId(function (d) { return d.parentId })
(result);
and then set the name you need to be displayed like this:
// assign the name to each node as the initial name
treeData.each(function(d) {
d.name = d.data.name;
});
A working example can be found here, based on this
:)
Good luck!
I am using a d3.js time.scale like this:
var xScale = d3.time.scale()
.domain(d3.extent(data, function(d) { return d.date; }))
.range([0, chartWidth]);
The data is like this:
var testData = [
{
"date": "2015-04-01T00:00:00.000Z",
"value": 200.00
},
{
"date": "2015-05-01T00:00:00.000Z",
"value": 2000.00
},
{
"date": "2015-06-01T00:00:00.000Z",
"value": 4000.01
},
{
"date": "2015-07-01T00:00:00.000Z",
"value": 1000.00
},
{
"date": "2015-08-01T00:00:00.000Z",
"value": 750.00
},
{
"date": "2015-09-01T00:00:00.000Z",
"value": 1568.00
},
{
"date": "2015-10-01T00:00:00.000Z",
"value": 3789.00
},
{
"date": "2015-11-01T00:00:00.000Z",
"value": 5678.00
},
{
"date": "2015-12-01T00:00:00.000Z",
"value": 4898.00
},
{
"date": "2016-01-01T00:00:00.000Z",
"value": 9002.00
},
{
"date": "2016-02-01T00:00:00.000Z",
"value": 3320.00
},
{
"date": "2016-03-01T00:00:00.000Z",
"value": 12000.00
}
];
But the ticks and the ordering are not as I would expect:
I would expect the ticks to be ordered from april 2015 to march 2016 and I do not understand where the 2016 tick is coming from.
How can I order the ticks as I would expect and also where is the 2016 tick coming from?
Here is a jsbin that shows the problem
If you want the ticks to show the month name and the year, add this to the axis:
.tickFormat(d3.time.format("%B %Y"));
Alternatively, you can display the abbreviated month name:
.tickFormat(d3.time.format("%b %Y"));
Here is the updated jsbin: http://jsbin.com/wikafuluqu/1/edit?js,output
PS: To show the first tick, add nice() to the scale. This is the jsbin with nice():
http://jsbin.com/loyupelazu/1/edit?js,output
When I select any particular field in the bar graph, all the graphs changes accordingly.
I want to introduce a heading above the graphs which should show which data is currently displayed in the graphs and the count.
So what changes should I make in my code?
var data = [{
"city": "New York",
"neighborhood": "N/A",
"hits": 200
}, {
"city": "New York",
"neighborhood": "Brooklyn",
"hits": 225
}, {
"city": "New York",
"neighborhood": "Queens",
"hits": 1
}, {
"city": "San Francisco",
"neighborhood": "Chinatown",
"hits": 268
}, {
"city": "San Francisco",
"neighborhood": "Downtown",
"hits": 22
}, {
"city": "Seattle",
"neighborhood": "N/A",
"hits": 2
}, {
"city": "Seattle",
"neighborhood": "Freemont",
"hits": 25
}];
var pieChart = dc.pieChart("#pieChart"),
rowChart = dc.rowChart("#rowChart");
var ndx = crossfilter(data),
cityDimension = ndx.dimension(function (d) {
return d.city;
}),
cityGroup = cityDimension.group().reduceSum(function (d) {
return d.hits;
}),
neighborhoodDimension = ndx.dimension(function (d) {
return d.neighborhood;
}),
neighborhoodGroup = neighborhoodDimension.group().reduceSum(function (d) {
return d.hits;
});
pieChart.width(200)
.height(200)
.slicesCap(4)
.dimension(cityDimension)
.group(cityGroup);
pieChart.filter = function() {};
rowChart.width(500)
.height(500)
.dimension(neighborhoodDimension)
.group(neighborhoodGroup);
dc.renderAll();
<div id="pieChart"> </div>
<div id="rowChart"> </div>
For displaying the current filters, you can use spans with class='reset' andclass='filter'` within the charts, as demonstrated in the annotated stock example
For displaying the counts of records filtered, you can use the dataCount widget or the numberDisplay widget.
Anything else, you'll have to implement the display itself, probably hooking the filtered event to determine when the filters have changed, and changing your own div using e.g. d3 or jQuery.
Why is my GeoJSON rendered like this with D3 given below code? (Should be a map of Uganda)
GeoJSON snippet
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"D_06_ID": 1,
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[472470.4185696139, 183515.90337615015]
Code
var projection = d3.geo.mercator()
.scale(60)
var path = d3.geo.path().projection(projection);
svg.selectAll(".subunit")
.data(data.features)
.enter().append("path")
.attr("d", path);