Discussions
Categories
Groups
Community Home
Categories
INTERNAL ENABLEMENT
POPULAR
THRUST SERVICES & TOOLS
CLOUD EDITIONS
Quick Links
MY LINKS
HELPFUL TIPS
Back to website
Home
Intelligence (Analytics)
stacked bar chart with value on y-axis and percent as value
somnix
<p>Hello ,</p>
<p> </p>
<p>here is the stacked bar chart that i have :</p>
<p> </p>
<div>[sharedmedia=core:attachments:13205]</div>
<div> </div>
<div>does anyone know how to display the percent OF THE STAKED BAR instead of the value </div>
<div> </div>
<div> </div>
<div>if i tryed to change the serie label value for "percentil value data" </div>
<div>it will display :</div>
<div> </div>
<div>
<div>on the first staked bar</div>
<div>serieA_2014 / total_serieA</div>
<div>serieB_2014 / total_serieB</div>
<div> </div>
<div>on the second staked bar</div>
<div>serieA_2015 / total_serieA</div>
<div>serieB_2015 / total_serieB</div>
<div> </div>
</div>
<div> </div>
<div>!!! BUT !!!</div>
<div> </div>
<div>i would like to display</div>
<div> </div>
<div>on the first staked bar</div>
<div>serieA_for_2014 / total_2014</div>
<div>serieB_for_2014 / total_2014</div>
<div> </div>
<div>
<div>on the second staked bar</div>
<div>serieA_for_2015 / total_2015</div>
<div>serieB_for_2015 / total_2015</div>
<div> </div>
<div> </div>
<div>AND no i don't want to use a percent stack, because i don't wanna lose the value on y-axis</div>
<div> </div>
<div> </div>
<div>Any idea ?</div>
<div> </div>
<div>thanks</div>
<div> </div>
<div>Ludo</div>
</div>
<p> </p>
Find more posts tagged with
Comments
Clement Wong
<p>It's possible, but you'll need to get the data, say in the <em>afterDataSetFilled </em>event, compute the percentages and then update the data labels accordingly.</p>
<p> </p>
<p>Looks like you are using Open Source BIRT? It would be easier if you're using commercial BIRT.</p>
<p> </p>
<p>I don't have an OS BIRT example handy, but maybe later in the week, I'll post one.</p>
pricher
<p>Hi,</p>
<p> </p>
<p>The <em>afterDataSetFilled </em>event is the right place to add your script to compute the total for each <em>category</em>. However, there's an added twist: every time the afterDataSetFilled event is called, you get the data set for a <em>series</em>. This means that you have to pivot the data and keep the result in an array saved as a persistent global variable. Once all the series are computed, you can calculate the percentage of each data point in the <em>beforeDrawDataPoint </em>event.</p>
<p> </p>
<p>So, here's the code. First, initialize a couple of persistent global variables in the <em>beforeFactory </em>method of the report:</p>
<pre class="_prettyXprint _lang-">
keepTotal = new java.util.ArrayList;
cnt = new java.lang.Integer(0);
reportContext.setPersistentGlobalVariable("g_keepTotal", keepTotal)
reportContext.setPersistentGlobalVariable("g_cnt", cnt);
</pre>
<p>Then, add the following script in the <em>onRender </em>of the chart:</p>
<pre class="_prettyXprint _lang-">
function afterDataSetFilled( series, dataSet, icsc )
{
var keepTotal = icsc.getExternalContext().getScriptable().getPersistentGlobalVariable("g_keepTotal");
var cnt = icsc.getExternalContext().getScriptable().getPersistentGlobalVariable("g_cnt");
var ds = dataSet.getValues();
if (cnt > 0) {
for (i = 0; i < ds.length; i++) {
var tmp = keepTotal.get(i) * 1;
tmp += ds[i] * 1;
keepTotal.set(i, tmp);
}
} else {
for (i = 0; i < ds.length; i++) {
keepTotal.add(new java.lang.Integer(0));
}
}
cnt++;
icsc.getExternalContext().getScriptable().setPersistentGlobalVariable("g_keepTotal", keepTotal);
icsc.getExternalContext().getScriptable().setPersistentGlobalVariable("g_cnt", new java.lang.Integer(cnt));
}
function beforeDrawDataPoint( dph, fill, icsc )
{
var keepTotal = icsc.getExternalContext().getScriptable().getPersistentGlobalVariable("g_keepTotal");
dph.setOrthogonalValue( (dph.getOrthogonalValue() / keepTotal[dph.getIndex()]) * 100 )
}
</pre>
<p>The full sample report is attached.</p>
<p> </p>
<p>Hope this helps,</p>
<p> </p>
<p>P.</p>
somnix
<p>hello Pierre ,</p>
<p> </p>
<p>thanks for your answer , but it s not what i m trying to do.</p>
<p> </p>
<p>i don't want to change the orthogonal value , i want to change the label to display for each year the the part of each serie / sum of all series.</p>
<p> </p>
<p>so i guess that the solution would be to be able to get access to the full data to calculate the sum of year before to start to display series</p>
<p>and be able to calculate the part.</p>
<p> </p>
<p>is it possible ?</p>
pricher
<p>Hi,</p>
<p> </p>
<p>This is exactly what my example is doing: calculate the sum of each year (in the <em><strong>afterDataSetFilled </strong></em>function) and the percentage of each series per year (in the <em><strong>beforeDrawDataPoint </strong></em>function). Setting the orthogonal value <em>before the data point is drawn</em> is akin to modifying the label and the right thing to do.</p>
<p> </p>
<p>This is the end result:</p>
<p> </p>
<p>
somnix
<p>Hello Pierre</p>
<p> </p>
<p>i m really sorry , i didn't understand well and my chart had a bug so the result was different.</p>
<p> </p>
<p>Your solution is perfect.</p>
<p> </p>
<p>Thanks again</p>
<p> </p>
<p>L.</p>
pricher
<p>Glad it works! Let us know if you need more help.</p>
<p> </p>
<p>P.</p>
vijayshankar245
<blockquote class="ipsBlockquote" data-author="pricher" data-cid="143513" data-time="1462288409">
<div>
<p>Hi,</p>
<p> </p>
<p>The <em>afterDataSetFilled </em>event is the right place to add your script to compute the total for each <em>category</em>. However, there's an added twist: every time the afterDataSetFilled event is called, you get the data set for a <em>series</em>. This means that you have to pivot the data and keep the result in an array saved as a persistent global variable. Once all the series are computed, you can calculate the percentage of each data point in the <em>beforeDrawDataPoint </em>event.</p>
<p> </p>
<p>So, here's the code. First, initialize a couple of persistent global variables in the <em>beforeFactory </em>method of the report:</p>
<pre class="_prettyXprint _lang-">
keepTotal = new java.util.ArrayList;
cnt = new java.lang.Integer(0);
reportContext.setPersistentGlobalVariable("g_keepTotal", keepTotal)
reportContext.setPersistentGlobalVariable("g_cnt", cnt);
</pre>
<p>Then, add the following script in the <em>onRender </em>of the chart:</p>
<pre class="_prettyXprint _lang-">
function afterDataSetFilled( series, dataSet, icsc )
{
var keepTotal = icsc.getExternalContext().getScriptable().getPersistentGlobalVariable("g_keepTotal");
var cnt = icsc.getExternalContext().getScriptable().getPersistentGlobalVariable("g_cnt");
var ds = dataSet.getValues();
if (cnt > 0) {
for (i = 0; i < ds.length; i++) {
var tmp = keepTotal.get(i) * 1;
tmp += ds[i] * 1;
keepTotal.set(i, tmp);
}
} else {
for (i = 0; i < ds.length; i++) {
keepTotal.add(new java.lang.Integer(0));
}
}
cnt++;
icsc.getExternalContext().getScriptable().setPersistentGlobalVariable("g_keepTotal", keepTotal);
icsc.getExternalContext().getScriptable().setPersistentGlobalVariable("g_cnt", new java.lang.Integer(cnt));
}
function beforeDrawDataPoint( dph, fill, icsc )
{
var keepTotal = icsc.getExternalContext().getScriptable().getPersistentGlobalVariable("g_keepTotal");
dph.setOrthogonalValue( (dph.getOrthogonalValue() / keepTotal[dph.getIndex()]) * 100 )
}
</pre>
<p>The full sample report is attached.</p>
<p> </p>
<p>Hope this helps,</p>
<p> </p>
<p>P.</p>
</div>
</blockquote>
<p>Hi Pierre</p>
<p> </p>
<p>I have a similar requirement where in I need to show Percentage of values for each category but not in stacked format.</p>
<p>Can you please if we could do these with the help of data model instead of a dataset.</p>
<p> </p>
<p>We have a data design built and are using .data as data source in our report. We are using one datamodel which consists of multiple tables data. we can't use dataset in our requirement.</p>
pricher
<p>Hi,</p>
<p> </p>
<p>If you are using a data model, it means you are using commercial BIRT, not Open Source. The solution I provided earlier was for O/S. If you are using commercial BIRT, you are most likely using HTML5 charts. In that case, the scripting is done using the Highcharts API, not the BIRT Chart Engine API.</p>
<p> </p>
<p>The fact that you are using data models doesn't matter. The way the data is interpreted in the chart is the same for data sets or data models.</p>
<p> </p>
<p>If you just want to show the percentage of values in a non stacked chart, there is no need to add scripting. You can choose "Percentile Value Data" from the drop-down list in Series --> Value Y Series --> Series Labels and add it to the Values. The code I provided earlier was for a special case where percentages are calculated based on the total of each Optional Y-Series per X-Axis category. The default behavior in that case is to calculate the percentage based on the total of each X-Axis category per Optional Y-Series. (Hope I am making sense here...)</p>
<p> </p>
<p>Hope this helps,</p>
<p> </p>
<p>P.</p>
shamo
<p>With Pierre's example in the stack percentages, you could also have used a crosstab and create a chat view out if you don't want to use script</p>
vijayshankar245
<blockquote class="ipsBlockquote" data-author="pricher" data-cid="144139" data-time="1464965437">
<div>
<p>Hi,</p>
<p> </p>
<p>If you are using a data model, it means you are using commercial BIRT, not Open Source. The solution I provided earlier was for O/S. If you are using commercial BIRT, you are most likely using HTML5 charts. In that case, the scripting is done using the Highcharts API, not the BIRT Chart Engine API.</p>
<p> </p>
<p>The fact that you are using data models doesn't matter. The way the data is interpreted in the chart is the same for data sets or data models.</p>
<p> </p>
<p>If you just want to show the percentage of values in a non stacked chart, there is no need to add scripting. You can choose "Percentile Value Data" from the drop-down list in Series --> Value Y Series --> Series Labels and add it to the Values. The code I provided earlier was for a special case where percentages are calculated based on the total of each Optional Y-Series per X-Axis category. The default behavior in that case is to calculate the percentage based on the total of each X-Axis category per Optional Y-Series. (Hope I am making sense here...)</p>
<p> </p>
<p>Hope this helps,</p>
<p> </p>
<p>P.</p>
</div>
</blockquote>
<p>Hi</p>
<p>The requirement is to show the percentage of Failure count across the total count for the last 6 weeks. the Percentage value in y axis and the date in X axis.Since Im using data model in my report, I need to create a new aggregate data to calculate the failure count, then divide the same from total count inorder to get the percentage. I wrote like BIRTDIVIDE(row(Failure_CNT),row(TOTAL_CNT)) but it doesnt work and throws index 0,size 0 error.</p>
<p> </p>
<p>Kindly help if it can be done without scripting, or if any scripting involved please post how can it be done.</p>
pricher
<p>Hi,</p>
<p> </p>
<p>Can you be a bit more specific about your requirement? I'm having a hard time visualizing what you are attempting to do. Since you are using a data model, can you send both the .data and .rptdesign? Or at least, a mock-up of the chart you are attempting to build?</p>
<p> </p>
<p>P.</p>
Kondaiah
<p>Hi Richer,</p>
<p> </p>
<p>this is kondaiah, I am new to BIRT framework. I am able to display 100% stacked bar chart with your code. But i am facing one problem, that i am displaying multiple pages of PDFs. In the first page stacked bar displaying results properly. but in the second graph stacked grapph is displaying NAN%. Please provide some solution around it.</p>
<p> </p>
<p>Thanks in Advance.</p>
<p>Kondaiah.</p>
pricher
<p>Hi,</p>
<p> </p>
<p>I have modified my example and it now displays 2 charts correctly. Instead of initializing the persistent variables in the beforeFactory of the report, it is now done at the beginning of the chart scripting. So, for each chart, the script looks like this:</p>
<pre class="_prettyXprint _lang-">
keepTotal = new java.util.ArrayList;
cnt = new java.lang.Integer(0);
/**
* Called after populating the series dataset.
*
*
@param
series
* Series
*
@param
dataSet
* DataSet
*
@param
icsc
* IChartScriptContext
*/
function afterDataSetFilled( series, dataSet, icsc )
{
var ds = dataSet.getValues();
if (cnt > 0) {
for (i = 0; i < ds.length; i++) {
var tmp = keepTotal.get(i) * 1;
tmp += ds[i] * 1;
keepTotal.set(i, tmp);
}
} else {
for (i = 0; i < ds.length; i++) {
keepTotal.add(new java.lang.Integer(0));
}
}
cnt++;
icsc.getExternalContext().getScriptable().setPersistentGlobalVariable("g_keepTotal", keepTotal);
icsc.getExternalContext().getScriptable().setPersistentGlobalVariable("g_cnt", new java.lang.Integer(cnt));
}
/**
* Called before drawing each datapoint graphical representation or marker.
*
*
@param
dph
* DataPointHints
*
@param
fill
* Fill
*
@param
icsc
* IChartScriptContext
*/
function beforeDrawDataPoint( dph, fill, icsc )
{
var keepTotal = icsc.getExternalContext().getScriptable().getPersistentGlobalVariable("g_keepTotal");
dph.setOrthogonalValue( (dph.getOrthogonalValue() / keepTotal[dph.getIndex()]) * 100 )
}
</pre>
<p>The new sample report is attached.</p>
<p> </p>
<p>Hope this helps,</p>
<p> </p>
<p>P.</p>
Kondaiah
<p>Thanks Richer,</p>
<p> </p>
<p>It works like charm. Your code helped me alot. Thank you once again.</p>