Height for chart area (not the canvas size)? - chart.js

Since GitHub is telling me "DO NOT create issues for questions or support requests." and doesn't mention another place to ask a question, I guess this is the place?
If I want to set a specific size for the charts (but not the overall size of the canvas), anyone knows if that is possible to do?
My reason is my X Axis labels can get really long, and when that happens, I simply increase the canvas size, but that obviously changes the whole size entirely. So I would like to set separate sizes for the chart area and the x axis label area...

With ChartJS
When your labels become little automatically the labels get vertically aligned as shown
And with Both Small and Large Size Label Canvas is consuming me Same Height and Width
width: 430px; height: 215px;
Large Label
$scope.labels = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
With Small Label
$scope.labels = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
HTML
<div class="col-md-4">
<div style="height:auto; width:auto;">
<div ng-controller="LinemsoVersionCtrl">
<canvas id="line" class="chart chart-line" chart-data="data" chart-labels="labels" chart-series="series" chart-options="options" chart-dataset-override="datasetOverride" chart-click="onClick"></canvas>
</div>
</div>
</div>
CSS
.col-md-4 {
width: 33.33333333%
}

Related

Apexchart and percent data labels

I am looking into using Apexcharts and would like to know if there is an option to have the data labels generated outside the slices with lines pointing to the associated slice? I have cases where the slice is small and prevents the application from generating the slice percent. This is a sample of what I am currently generating:
As you can see, there are 3 slices that do not show a percentage, I assume because the area of slice is to small to generate the percentage. If the percentages could be rendered outside the slice with a line or arrow pointing to its associated slice, that would be great. Is that option available?
Any ideas?
Thank you.
If you want to show the percentage values outside the slices, if yes then you do this:
dataLabels: {
enabled: true,
style: {
offsetX: -6,
colors: ['#333'],
fontSize: '11px',
fontFamily: 'Helvetica, Arial, sans-serif',
fontWeight: 'bold',
},
},
Read more

how to resize specific gridline(s) in chart.js

I want to get a line width of 10 on specific points in the chart.
I can get a line width of 10 but on all lines with the following code:
gridLines: {
display: true,
lineWidth: 10
},
Current chart:
Is it possible to add specific width on different gridlines
What i want:
Codepen:
https://codepen.io/flowwdelapro/pen/RwPMbvb
You have to use an array instead of a number.
lineWidth: [1,1,10,1,10]
The number are applied from left to right.

xml data handling regex find replace with conditional values

I got a xml file which looks like this
<DocumentElement>
<Table1>
<Date>2013-08-24</Date>
<Time>00:07:23</Time>
<Type>in</Type>
<Number>393483419761</Number>
<Name>Marc</Name>
<Message>Lorem ipsum</Message>
</Table1>
<Table1>
<Date>2013-08-24</Date>
<Time>00:09:09</Time>
<Type>out</Type>
<Number>1215468498561</Number>
<Name>Marc</Name>
<Message>Lorem ipsum</Message>
</Table1>
<DocumentElement>
What I want to do is Check the Date Value and if the Month is 01, add <Month>january</Month> after </Date>, and if month is 02 add <Month>february</Month> and so on.
So what I got so far is either:
<Date>(\d{4})-01-(\d{2})</Date>
<Date>$1-01-$2</Date>
<Month>january</Month>
or i'd like to do something like:
<Date>(\d{4})-(\d{2})-(\d{2})</Date>
if ($2 = 01) {
<Date>$1-$2-$3</Date>
<Month>january</Month>
}
elseif ($2 = 02) {
<Date>$1-$2-$3</Date>
<Month>february</Month>
}
whats the usual way to handle and manipulate data like this?
Normally if you are parsing XML you would use a real parser instead of regular expressions. But in your particular case it is a very simple operation you want do do. Go over each line, print it, and if the current line is a date, extract the month and print an additional line.
Here's an example python script that does that.
import re
months = ["January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"]
with open(your_xml_file) as f:
for line in f:
print line
match = re.search(r'<Date>\d{4}-(?P<month>\d{2})-\d{2}</Date>', line)
if match is not None:
print months[int(match.group('month')) - 1]
Note, however that this will fail as soon as you insert whitespace or add something else like attributes to Date. That's why it's better to use a real parser. But if your format is exactly like you stated, then it is faster to just write a small throw away script like this.
so just for the record this is my final code which adds another regex substitution and outputs everything in a new file:
x = 'marco_2013_24_08' #filename without extension
import re
months = ["<Month>gennaio</Month>", "<Month>febbraio</Month>", "<Month>marzo</Month>", "<Month>aprile</Month>", "<Month>maggio</Month>", "<Month>giugno</Month>", "<Month>luglio</Month>",
"<Month>agosto</Month>", "<Month>settembre</Month>", "<Month>ottobre</Month>", "<Month>novembre</Month>", "<Month>dicembre</Month>"]
import sys
sys.stdout = open('_' + x + 'regexed.xml', 'w')
with open(x + '.xml') as f:
for line in f:
im = re.sub(r'<Message>Image\:\ .+\/(IMG.+\.jpg)<\/Message>',r'<Image href="Bilder/\1"></Image>',line)
print im
mm = re.search(r'<Date>\d{4}-(?P<month>\d{2})-\d{2}</Date>', line)
if mm is not None:
print months[int(mm.group('month')) - 1]

Show all values in stacked area charts at given time

Amazon did a great job with the monitoring in OpsWorks (see screenshot). You can point at any time in any of the area charts and see all values for all charts at that time.
Is it possible to achieve something similar with the Google Visualisation API?
I also have multiple (stacked) area charts and it's a pain to point at each datapoint to get the exact value. Some of them are overlapping or very close together.
You can't trigger the tooltips in all of the charts at the same time, but if you disable the built-in tooltips, you can achieve something similar by building out your tooltips in HTML and populating them manually in a "onmouseover" event handler:
function mouseOverHandler (e) {
// use e.row, e.column to find data and populate your tooltips
}
function mouseOutHandler (e) {
// clear the tooltips
}
google.visualization.events.addListener(chart1, 'onmouseover', mouseOverHandler);
google.visualization.events.addListener(chart1, 'onmouseout', mouseOutHandler);
google.visualization.events.addListener(chart2, 'onmouseover', mouseOverHandler);
google.visualization.events.addListener(chart2, 'onmouseout', mouseOutHandler);
// etc...
In your stacked area chart (assuming you do not replace the tooltips with a custom solution), you can set the focusTarget option to 'category' to make all values at a given x-axis value show up in the tooltip (works only within one chart, not across charts).
You can also cheat by putting all three charts in the same chart element with a little trickery (and some limitations). For instance, you can make the chart like this:
Here is the code for that (dummy data):
function drawVisualization() {
// Some raw data (not necessarily accurate)
var data = new google.visualization.DataTable();
data.addColumn('number', 'time');
data.addColumn('number', 'used');
data.addColumn('number', 'cached');
data.addColumn('number', 'free');
data.addColumn('number', 'user');
data.addColumn('number', 'system');
data.addColumn('number', 'io wait');
data.addColumn('number', '1 min');
data.addColumn('number', '5 min');
data.addColumn('number', '15 min');
data.addRows([
[1, {v:0.1, f:'10%'},{v:0.55, f:'45%'},{v:1, f:'45%'},{v:1.01, f:'0.15 GiB'},{v:1.83, f:'12.45 GiB'},{v:1.18, f:'2.7 GiB'},{v:2.28166561658701, f:'28.2%'},{v:2.38024858239246, f:'38.0%'},{v:2.42249842488051, f:'42.2%'}],
[2, {v:0.2, f:'20%'},{v:0.6, f:'40%'},{v:1, f:'40%'},{v:1.54, f:'8.1 GiB'},{v:1.47, f:'7.05 GiB'},{v:1.77, f:'11.55 GiB'},{v:2.53503269167234, f:'53.5%'},{v:2.74904576834128, f:'74.9%'},{v:2.4119751725877, f:'41.2%'}],
[3, {v:0.3, f:'30%'},{v:0.65, f:'35%'},{v:1, f:'35%'},{v:1.13, f:'1.95 GiB'},{v:1.15, f:'2.25 GiB'},{v:1.75, f:'11.25 GiB'},{v:2.73464579773048, f:'73.5%'},{v:2.85218912536736, f:'85.2%'},{v:2.80811037750353, f:'80.8%'}],
[4, {v:0.4, f:'40%'},{v:0.7, f:'30%'},{v:1, f:'30%'},{v:1.27, f:'4.05 GiB'},{v:1.86, f:'12.9 GiB'},{v:1.1, f:'1.5 GiB'},{v:2.86045009159487, f:'86.0%'},{v:2.92068159800651, f:'92.1%'},{v:2.54208355770477, f:'54.2%'}],
[5, {v:0.5, f:'50%'},{v:0.75, f:'25%'},{v:1, f:'25%'},{v:1.23, f:'3.45 GiB'},{v:1.12, f:'1.8 GiB'},{v:1.88, f:'13.2 GiB'},{v:2.89980619585711, f:'90.0%'},{v:2.8728120099814, f:'87.3%'},{v:2.75583720451997, f:'75.6%'}],
[6, {v:0.6, f:'60%'},{v:0.8, f:'20%'},{v:1, f:'20%'},{v:1.5, f:'7.5 GiB'},{v:1.78, f:'11.7 GiB'},{v:1.26, f:'3.9 GiB'},{v:2.84876005903125, f:'84.9%'},{v:2.66203284604438, f:'66.2%'},{v:2.63657004427344, f:'63.7%'}],
[7, {v:0.7, f:'70%'},{v:0.85, f:'15%'},{v:1, f:'15%'},{v:1.91, f:'13.65 GiB'},{v:1.26, f:'3.9 GiB'},{v:1.69, f:'10.35 GiB'},{v:2.71244021344925, f:'71.2%'},{v:2.78368423479417, f:'78.4%'},{v:2.69819140918026, f:'69.8%'}],
[8, {v:0.8, f:'80%'},{v:0.9, f:'10%'},{v:1, f:'10%'},{v:1.48, f:'7.2 GiB'},{v:1.51, f:'7.65 GiB'},{v:1.41, f:'6.15 GiB'},{v:2.50454251895529, f:'50.5%'},{v:2.59031474717769, f:'59.0%'},{v:2.33299806251049, f:'33.3%'}],
[9, {v:0.9, f:'90%'},{v:0.95, f:'5%'},{v:1, f:'5%'},{v:1.18, f:'2.7 GiB'},{v:1.53, f:'7.95 GiB'},{v:1.97, f:'14.55 GiB'},{v:2.24595415946281, f:'24.6%'},{v:2.24103507627355, f:'24.1%'},{v:2.22381828511115, f:'22.4%'}],
[10, {v:1, f:'100%'},{v:1, f:'0%'},{v:1, f:'0%'},{v:1.66, f:'9.9 GiB'},{v:1.61, f:'9.15 GiB'},{v:1.2, f:'3 GiB'},{v:2.1229770797314, f:'12.3%'},{v:2.13527478770454, f:'13.5%'},{v:2.14757249567768, f:'14.8%'}],
]);
// Create and draw the visualization.
var ac = new google.visualization.AreaChart(document.getElementById('visualization'));
ac.draw(data, {
title : 'Monthly Coffee Production by Country',
isStacked: false,
width: 600,
height: 400,
areaOpacity: 0.0,
focusTarget: 'category',
series: { 0: {areaOpacity: 0.5}, 1: {areaOpacity: 0.5}, 2: {areaOpacity: 0.5} },
vAxis: { ticks: [{v:0, f:""}, {v:0.5, f:"7.5 GiB"}, {v:1, f:"15.0 GiB"}, {v:1.5, f:"50%"}, {v:2, f:"100%"}, {v:2.5, f:"50%"}, {v:3, f:"100%"}, ] }
});
}
Basically, I put all 3 series on the same chart by putting them all as percentages of 1/3rd of the chart. So the first series is from 0-1, the second from 1-2, and the third from 2-3. I then used liberal quantities of {v:, f:} notation to make them look like different numbers (for the GiB particularly), and used the ticks option to make the axis look like it has 3 scales. Finally, I set focusTarget: 'category' so all lines get selected when you mouseover any of them.
You can format colors and even add dummy series to add thicker black lines between the series if you want to make them look more 'distinct'. You can also do some tricky stuff with dummy series and white areas and 100% opacity to potentially add background colors to higher areas. But the general concept is as outlined above, depending on what you are going for, it could work too.

Google Chart Customization

I want following Google Chart (Column Chart) to show its first label on horizontal axis. Also I want each column to have same width; first and last column need a change. How is it possible?
var chartDataRaw = [{
"month": "201211",
"articles": 41467
}, {
"month": "201212",
"articles": 31820
}, {
"month": "201301",
"articles": 43817
}, {
"month": "201302",
"articles": 42773
}, {
"month": "201303",
"articles": 38695
}, {
"month": "201304",
"articles": 41257
}];
var dataTable = new google.visualization.DataTable();
dataTable.addColumn('date', 'Month');
dataTable.addColumn('number', 'Articles');
var i = 1;
//chartDataRaw is array of objects, requested from server. looped through jquery each to fill dataTable
$.each(chartDataRaw, function () {
var year = this.month.substring(0, 4);
var month = this.month.substring(4);
var dataItem = [new Date(year, month), this.articles];
dataTable.addRow(dataItem);
});
var options = {
title: 'Company Coverage',
hAxis: {
title: 'Last Six Months',
titleTextStyle: {
color: 'red'
},
format: 'MMM, yyyy',
fontSize: '8px'
},
vAxis: {
textPosition: 'none'
},
trendlines: {
0: {
color: 'black',
lineWidth: 3,
opacity: 0.4
}
},
legend: 'none'
};
var monthYearFormatter = new google.visualization.DateFormat({
pattern: "MMM, yyyy"
});
monthYearFormatter.format(dataTable, 0); //change date format to render on chart
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
chart.draw(dataTable, options);
http://jsfiddle.net/YyYsN/2/
Edit: Added chart data
Executive Summary
You are committing several mortal sins:
You are not defining dates right
You have no y axis values distorting your data
You are using columns to describe a continuous series
You are predicting based on only 6 data points
You are not defining dates right
Look at the value for January 2013. It says 31,820 articles. The issue is your data says there were 43,817 articles in January. What the heck is going on?
Javascript Date Objects use month values from 0-11, not 1-12. That means when you convert the dates, you need to change your function.
Old:
var dataItem = [new Date(year, month), this.articles];
New:
var dataItem = [new Date(year, month - 1), this.articles];
You have no y axis values distorting your data
Compare the second bar to the third bar. What is the ratio between the two? It looks like the second bar is around .5 gridlines, and the third bar is around 3.5 gridlines. That is a 700% increase in articles!
Only if you look at the data, it's actually going from 31,820 to 43,817, and increase of only 37%.
Bar charts should always start from zero, otherwise you get incredibly distorted perspective of the data, especially when there are no labels to boot.
Old:
vAxis: {
textPosition: 'none',
},
New:
vAxis: {
textPosition: 'none',
minValue: 0
},
You are using columns to describe a continuous series
Columns show discrete items. If I want to poll how many kids in a class like dogs, cats, and iguanas, a column chart is great since it allows me to compare the popularity (height) across unrelated categories (horizontal). Columns are okay for showing sales per month (or articles per month), but by making them columns you are implying that the columns should be compared as individual items, not as a progressing series.
If you want to show that these data items are connected (as implied by the trendline) it would make much more sense to show an area chart.
(Ideally, the area chart would show articles over the last 30 days, and have daily data, rather than a monthly compilation since months are arbitrary cutoffs, and things like weekends and holidays probably have a significant impact on your data which further distorts what you're trying to show).
Old
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
New
var chart = new google.visualization.AreaChart(document.getElementById('chart_div'));
You are predicting based on only 6 data point
Six points does not a trend make. Your data's highest value is the second point, yet you are showing the trend increasing over time. Perhaps the trendline suggests an upward trend (since the later values are higher than the first value), but as soon as you move 1 month forward you will have a descending trendline (barring a massive increase in articles).
This makes no rational sense. 5 months of data are the same. How can changing 1 month of a 6-month series change the direction of the trendline? Forecasting is iffy-enough as it is (see the Black Swan theory), but doing it on a minimal 6-month series likely isn't the best. This means the trendline should probably be removed altogether since it not only doesn't convey useful information, it potentially conveys incorrect information.
Summary
That said, if you just want your left and right columns not to be cut off, you can change the following code:
Old
hAxis: {
title: 'Last Six Months',
titleTextStyle: {
color: 'red'
},
format: 'MMM, yyyy',
fontSize: '8px',
},
New
hAxis: {
title: 'Last Six Months',
titleTextStyle: {
color: 'red'
},
format: 'MMM, yyyy',
fontSize: '8px',
minValue: new Date(2012,9),
maxValue: new Date(2013,4)
},
fixed it myself by changing corechart visualization version to 1.1
google.load("visualization", "1.1", {packages:["corechart"]});