I'm trying to convert my csv to the format needed by nvd3's stacked area chart: http://nvd3.org/ghpages/stackedArea.html
but got lost in the arrays conversion. Can someone help?
csv:
length,m1,m2,m3,m4
9,1,2,3,4
99,11,22,33,44
999,111,222,333,444
format needed by nvd3
var histcatexplong = [
{
"key" : "Consumer Discretionary" ,
"values" : [ [ 0000000000000 , 27.38478809681] , [ 0000000000000 , 27.371377218208] , [ 0000000000000 , 26.823411519395] } ,
{
"key" : "Consumer Staples" ,
"values" : [ [ 0000000000000 , 27.45458809681] , [ 0000000000000 , 27.444444444408] , [ 0000000000000 , 26.455555555395] } ,
so if the conversion is right, I should get:
var myall = [
{
"key" : "m3" ,
"values" : [ [ 9 , 3] , [ 99, 33] , [ 999, 333] } ,
{
"key" : "m1" ,
"values" : [ [ 9 , 1] , [ 99, 11] , [ 999, 111] } ,
My code for the conversion:
d3.csv("s1.csv", function (csv) {
var myall = [
{
"key" : "m3",
"values" : []
},
{
"key" : "m2",
"values" : []
}
];
v3 = csv.map(function(d) { return [ +d["length"], +d["m3"] ]; });
v2 = csv.map(function(d) { return [ +d["length"], +d["m2"] ]; });
d3.keys(csv).forEach(function(d) {
myall[0].values.push(v3);
myall[1].values.push(v2);
});
console.log(myall);
The problem is that myall didn't show up in the DOM (console output seems to be missing a top hierarchy:
[Object { key="m345", values=[249]}, Object { key="m2", values=[249]}]
For the nvd3 stacked area chart example, DOM copy/paste for the histcatexplong var:
*histcatexplong
[Object { key="Consumer Discretionary", values=[77]}, Object { key="Consumer Staples", values=[77]}, Object { key="Energy", values=[77]}, 7 more...]*
Thanks.
After some debugging, I fixed the issue. As a help to fellow learners, I post the code.
This is useful for people that need:
a. nvd3 stacked area chart(gives you the tooltips and other utilities for free i.e. no extra programming)
b. x-axis with values instead of dates
c. has csv data (flat hierarchy) in this format:
length,m1,m2
103.10,111,2222
137.91,0.36980639547531,99.6301936045247
113.30,0.176522506619594,99.8234774933804
159.59,0.244376214048499,99.7556237859515
code (modified from http://nvd3.org/ghpages/stackedArea.html):
<script>
<!DOCTYPE html>
<meta charset="utf-8">
<link href="../src/nv.d3.css" rel="stylesheet" type="text/css">
<style>
body {
overflow-y:scroll;
}
text {
font: 12px sans-serif;
}
#chart1, #chart2 {
height: 500px;
}
</style>
<body>
<div>
<svg id="chart1"></svg>
</div>
<script src="../lib/d3.v3.js"></script>
<script src="../nv.d3.js"></script>
<script src="../src/utils.js"></script>
<script src="../src/models/axis.js"></script>
<script src="../src/tooltip.js"></script>
<script src="../src/models/legend.js"></script>
<script src="../src/models/axis.js"></script>
<script src="../src/models/scatter.js"></script>
<script src="../src/models/stackedArea.js"></script>
<script src="../src/models/stackedAreaChart.js"></script>
<script>
var myall = [
{
"key" : "m1",
"values" : []
},
{
"key" : "m2",
"values" : []
}
];
d3.csv("s1.csv", function (error, csv) {
if (error) return console.log("there was an error loading the csv: " + error);
console.log("there are " + csv.length + " elements in my csv set");
csv.sort(function(a,b) {return a.length-b.length;});
var mmm = ["m1","m2"];
for (var i = 0; i < mmm.length; i++) {
myall[i].values = csv.map(function(d) { return [ +d["length"], +d[mmm[i]] ]; });
};
var colors = d3.scale.category20();
keyColor = function(d, i) {return colors(d.key)};
var chart;
nv.addGraph(function() {
chart = nv.models.stackedAreaChart()
.x(function(d) { return d[0] })
.y(function(d) { return d[1] })
.color(keyColor)
.clipEdge(true);
// chart.xAxis
// .tickFormat(function(d) { return d3.time.format('%x')(new Date(d)) });
chart.yAxis
.tickFormat(d3.format(',.2f'));
d3.select('#chart1')
.datum(myall)
.transition().duration(500).call(chart);
nv.utils.windowResize(chart.update);
chart.dispatch.on('stateChange', function(e) { nv.log('New State:', JSON.stringify(e)); });
return chart;
});
// end read csv
});
Related
I am trying to create a timeseries using the nvd3 lineWithFocusChart model. My data is an array of objects like this:
[
{
"key": "red",
"values": [
{
"date": "2015-06-17T11:00:00.000Z",
"value": 17
},
...]
},
{
"key": "green",
"values": [
{
"date": "2015-06-17T11:00:00.000Z",
"value": 20
},
...]
},
]
I just want to map date to x and value to y, which looking at other examples is typically done like this:
nv.addGraph(function() {
var chart = nv.models.lineWithFocusChart()
.x(function(d) { return new Date(d.daterun)})
.y(function(d) { return d.value});
chart.brushExtent([50,70]);
chart.xAxis.tickFormat(d3.format(function(d) {
return d3.time.format('%x')(new Date(d));
}));
chart.x2Axis.tickFormat(d3.format(',f'));
chart.yAxis.tickFormat(d3.format(',.2f'));
chart.y2Axis.tickFormat(d3.format(',.2f'));
chart.useInteractiveGuideline(true);
d3.select('#chart svg')
.datum(data)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
But on the .x(function(d) { return new Date(d.date)}) I am getting TypeError: d is undefined.
How can I map my data correctly for this chart model?
I have created the following code from the parts you provided I do not receive the error that you refer to, my lines do not draw probably because I only have two points of data. See below:
<link href="libs/nv.d3.css" rel="stylesheet" type="text/css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.2/d3.min.js" charset="utf-8"></script>
<script src="libs/nv.d3.js"></script>
<script src="libs/stream_layers.js"></script>
<body>
<div id="chart" class='with-3d-shadow with-transitions'>
<svg></svg>
</div>
<script>
nv.addGraph(function() {
var chart = nv.models.lineWithFocusChart()
.x(function(d) { return new Date(d.date)})
.y(function(d) { return d.value});
chart.brushExtent([50,70]);
chart.xAxis.tickFormat(d3.format(function(d) {
return d3.time.format('%x')(new Date(d.date));
}));
chart.x2Axis.tickFormat(d3.format(',f'));
chart.yAxis.tickFormat(d3.format(',.2f'));
chart.y2Axis.tickFormat(d3.format(',.2f'));
chart.useInteractiveGuideline(true);
d3.select('#chart svg')
.datum(data())
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
function data() {
return [
{
"key": "red",
"values": [
{
"date": "2015-06-17T11:00:00.000Z",
"value": 17
},
{
"date": "2015-06-17T11:00:00.000Z",
"value": 18
},
]
},
{
"key": "green",
"values": [
{
"date": "2015-06-17T11:00:00.000Z",
"value": 20
},
{
"date": "2015-06-17T11:00:00.000Z",
"value": 17
},
]
}
]
}
</script>
</body>
the only thing I found which was wrong is that you're referring to your date data point as "d.daterun" and in data as "date" which should be as "d.date" in code.
Hope this helps.
I have json data in the following format :
[{
"label" : "A Label" ,
"value" : -29.765957771107
} ,
{
"label" : "B Label" ,
"value" : 0
} ,
{
"label" : "C Label" ,
"value" : 32.807804682612
} ,
{
"label" : "D Label" ,
"value" : 196.45946739256
}]
I want to create a bar chart in NVD3 where x coordinates will be label and the y coordinates will be the value. So how can I achieve it. I have gone through many examples where the JSON data was used is a different format but my data is as shown above.
EDITED CODE:
Here is the js code through which I am trying to create a chart in NVD3 .
d3.json("http://localhost:8080/api/study", function(data) {
nv.addGraph(function() {
var chart = nv.models.multiBarHorizontalChart().x(function(d) {
return d.label;
}).y(function(d) {
return d.value;
}).margin({
top : 30,
right : 20,
bottom : 50,
left : 175
}).showValues(true)//Show bar value next to each bar.
.tooltips(true)//Show tooltips on hover.
//.transitionDuration(350)
.showControls(true);
//Allow user to switch between "Grouped" and "Stacked" mode.
chart.yAxis.tickFormat(d3.format(',.2f'));
d3.select('#chart11 svg').datum(data).call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
});
Most charts in nvd3.js have the following data sceleton:
[
{
key: "<Series name>",
color: "<CSS color>",
values: [
{x: 0, y: 10},
{x: 1, y: 20},
{x: 2, y: 30}
....
]
},
{
key: "<Series name>"
...
}
]
In your case the following format will be valid:
[
{
key: "Series 1",
values: [
{
"label" : "A Label" ,
"value" : -29.765957771107
} ,
{
"label" : "B Label" ,
"value" : 0
} ,
{
"label" : "C Label" ,
"value" : 32.807804682612
} ,
{
"label" : "D Label" ,
"value" : 196.45946739256
}
]
}
]
You will need to specify axis properties accessors:
var chart = nv.models.discreteBarChart()
.x(function(d) { return d.label })
.y(function(d) { return d.value })
I'm a newbie for Meteor.js but however I need to make some chart like http://nvd3.org/examples/pie.html. Bu I have no idea to render data on my html page.
Pie = new Meteor.Collection("pie");
if (Meteor.isClient) {
Template.chart.created = function(){ //not sure for template style.
_.defer(function () {
Deps.autorun(function () {
pp = Pie.find({}, {fields: {_id: 0}});
exampleData = _.toArray(pp);
console.log(exampleData);
//Regular pie chart example
nv.addGraph(function() {
var chart = nv.models.pieChart()
.x(function(d) { return d.label })
.y(function(d) { return d.value })
.showLabels(true);
d3.select("#chart svg")
.datum(exampleData)
.transition().duration(350)
.call(chart);
return chart;
});
//Donut chart example
nv.addGraph(function() {
var chart = nv.models.pieChart()
.x(function(d) { return d.label })
.y(function(d) { return d.value })
.showLabels(true) //Display pie labels
.labelThreshold(.05) //Configure the minimum slice size for labels to show up
.labelType("percent") //Configure what type of data to show in the label. Can be "key", "value" or "percent"
.donut(true) //Turn on Donut mode. Makes pie chart look tasty!
.donutRatio(0.35) //Configure how big you want the donut hole size to be.
;
d3.select("#chart2 svg")
.datum(exampleData)
.transition().duration(350)
.call(chart);
return chart;
});
});
});
}
}
if (Meteor.isServer) {
Meteor.startup(function () {
if(Pie.find().count() === 0) {
var data = [
{
"label": "One",
"value" : 29.765957771107
} ,
{
"label": "Two",
"value" : 0
} ,
{
"label": "Three",
"value" : 32.807804682612
} ,
{
"label": "Four",
"value" : 196.45946739256
} ,
{
"label": "Five",
"value" : 0.19434030906893
} ,
{
"label": "Six",
"value" : 98.079782601442
} ,
{
"label": "Seven",
"value" : 13.925743130903
} ,
{
"label": "Eight",
"value" : 5.1387322875705
}
];
for(var i=0; i < data.length; i++){
Pie.insert({
label: data[i].label,
value: data[i].value
});
}
}
});
}
d3.html
<head>
<meta charset="utf-8">
<title>d3</title>
</head>
<body>
{{> chart}}
</body>
<template name="chart">
<div width="500" height="500">
<svg id="chart"></svg>
<svg id="chart2"></svg>
</div>
</template>
As tested with Meteor both prior to Blaze and with Blaze: it is enough to start your Deps.autorun in the rendered callback of the template and just put your d3 drawing code there.
In Meteor prior to v.0.8.0, you would need to wrap the svg part into #constant region but once you use Blaze, it is not necessary.
An alternative is to draw everything once in rendered callback and then start observeChanges and keep your d3 view-model up to date.
I have a simple example here: https://github.com/Slava/d3-meteor-basic
I have a kendo grid with a column template. I try to pass a value from the current row as a parameter for my javascript function. My code:
{
field: "CrmTaskId",
title: "Crm ",
template: '<a href="javascript:hrefTest(#=CrmTaskId#);" ># if( CrmTaskId==null) {#<span><span># } else {#<span>#: CrmTaskId#<span>#} #</a>'
}
hrefTest is javascript function with one param. But it's not working. Any ideas?
It can be done like this
.ClientTemplate("<a href='javascript: void(0);'
onclick=\"return YourJSFunction('#= OpportunityUrl #');\">#= OpportunityName #</a>")
This is part of the column definition, so what it is saying is...Make the OpportunityName
clickable and pass in the OpportunityUrl. #= Field # is the syntax for pulling values off of the Model.
I have tried with your code but not able to reproduce this issue. Please create new HTML/CSHTML page and check it.
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<link href="http://cdn.kendostatic.com/2014.1.318/styles/kendo.common.min.css" rel="stylesheet" />
<link href="http://cdn.kendostatic.com/2014.1.318/styles/kendo.default.min.css" rel="stylesheet" />
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://cdn.kendostatic.com/2014.1.318/js/kendo.all.min.js"></script>
</head>
<body>
<div id="grid"></div>
<script>
var movies = [
{ "CrmTaskId": 1, "rating": 9.2, "year": 1994, "title": "The Shawshank Redemption"},
{ "CrmTaskId": 2, "rating": 9.2, "year": 1972, "title": "The Godfather"},
{ "CrmTaskId": null, "rating": 9, "year": 1974, "title": "The Godfather: Part II" },
{ "CrmTaskId": '', "rating": 9.9, "year": 1874, "title": "The Godmother: Part III" }
];
function hrefTest(CrmTaskId)
{
alert("CrmTaskId is: " + CrmTaskId);
}
$(document).ready(function () {
$("#grid").kendoGrid({
dataSource: {
data: movies,
pageSize: 10
},
groupable: true,
sortable: true,
pageable: {
refresh: true,
pageSizes: true
},
columns: [{
field: "CrmTaskId",
title: "Crm"
}, {
field: "title",
title: "title"
},
{
template: '<a href="javascript:hrefTest(#=CrmTaskId#);" ># if( CrmTaskId==null) {#<span><span># } else {#<span>#: CrmTaskId#<span>#} #</a>'
}
]
});
});
</script>
</body>
</html>
Please try with the below code snippet.
Use this :
{
field: "Field",
editable: true,
title: "Title",
template: showRelatedLink,
allownull: true,
width: 100
}
and then in your function :
function showRelatedLink(container, options)
{
var yourVariable = container.YourField;
}
You can pass a field to a function like this too:
Grid:
columns: [
{ field: "ProductTypeID", title: "Type", template: "#=product_type_to_name(ProductTypeID)#" },
]
Function:
function product_type_to_name(product_type_id) {
console.log(product_type_id);
var name = "";
// convert ID to name
return name;
}
I have tried this
{
field: "DisplayChangedFrom",
title: "From",
template:"#=generateTemplate(DisplayChangedFrom)#
},
Then the function
function generateTemplate(items) {
var html = "<ul>";
if (items !== null && items.length > 0) {
for (var x = 0; x < items.length; x++) {
html += "<li>";
html += items[x];
html += "</li>";
}
}
html += "</ul>";
return html;
};
I'm using jqPlot to graph out some weight data... if I dont specify just showing the year on the xAxis, the display is cluttered... but it seems like I can't get the full date to show when any data point is highlighted. Is there any way to get the highlighter to use a date-aware formatter, rather than the simple printf stuff?
<link rel="stylesheet" type="text/css" hrf="jqPlot/jquery.jqplot.min.css" />
<script>
$(document).ready(function(){
var line1=
[['1999.03.17',205],
['2001.06.15',189],
['2001.10.11',179],
['2004.01.09',192.5 ],
['2006.04.12',221.5],
['2007.12.06',216.5],
['2009.01.26',220],
['2010.06.22',215],
['2011.01.03',210],
['2012.04.20',208],
['2012.05.09',207.8],
['2013.05.03',201.2],
['2014.01.23',190.9]
];
var plot2 = $.jqplot('chart2', [line1], {
highlighter: {
show: true,
formatString: "%s %d",
tooltipAxes:'xy'
},
axes:{
xaxis:{
renderer:$.jqplot.DateAxisRenderer,
tickOptions:{formatString:'%y'},
tickInterval:'1 years'
}
},
series:[{lineWidth:4, markerOptions:{show:false}}]
});
});
Here is the solution: JsFiddle
$(document).ready(function () {
function tooltipeditor(str, seriesIndex, pointIndex, plot) {
var data = plot.data[seriesIndex][pointIndex]
return "<div>" + data[0] + " , " + data[1] + "</div>";
}
var line1 =
[
['1999/03/17', 205],
['2001/06/15', 189],
['2001/10/11', 179],
['2004/01/09', 192.5],
['2006/04/12', 221.5],
['2007/12/06', 216.5],
['2009/01/26', 220],
['2010/06/22', 215],
['2011/01/03', 210],
['2012/04/20', 208],
['2012/05/09', 207.8],
['2013/05/03', 201.2],
['2014/01/23', 190.9]
];
var plot2 = $.jqplot('chart1', [line1], {
highlighter: {
show: true,
tooltipContentEditor: tooltipeditor
},
axes: {
xaxis: {
renderer: $.jqplot.DateAxisRenderer,
tickOptions: {
formatString: '%y'
},
//tickInterval: '1 years'
}
},
series: [{
lineWidth: 4,
markerOptions: {
show: true
},
}]
});
});