I'm using the MPAndroidChart library, trying to customize the Stacked Bars.
The objective is to display the differences between 2 currencies.
So suppose this example for January.
Currency #1 = 8;
Currency #2 = 12
The idea is to show in the same bar both values, but instead of sum the 2 values ( 8 + 12) to have the value 8 "in front" and the value 12 "behind".
So the total high of the bar is the max value.
I tried to do that, extending the BarEntry class, and instead of calculate the sum, just set the max value. But I'm seeing only one bar now (the one with value = 12)
Do you know if this kind of logic is supported? Any advice?
Check out the guide on how to create stacked-bar-charts, as well as the example.
Create an entry in the stacked-bar-chart in the following way:
BarEntry entry = new BarEntry(xValue, new float[] { 8f, 12f });
This will create an entry with a total height of 20, consisting of two different values (8 and 12). The "xValue" is the position this bar will show up on the x-axis.
You can use as many entries for the stack (float array) as you want.
If you intend to do only single entries (no stacks), do not use the BarEntry constructor that takes a float array, use the one that only takes a single value.
Related
The Problem I am having is that I have charts which should always show a fixed range of XValues let's say all 24 hours in a day, but the Chart is only showing XValues up to and starting from the point of the first and last YValue, that is if I have two Y events, let's say 2am and 3pm, instead of showing the whole 24 hours, it will start at 2am and end at 3pm.
I think this has something to do with the new way to handle XValues via IAxisValueFormatter, since this used to work fine when we could add both X and Y values to a ChartData.
One hack to workaround this I found is to add empty YValues to first and last hour in my case 0 values, but this brings another issue that no matter what I set the minimum in LeftAxis it starts showing negative label values (starts in -15 instead of 0).
Is there an official way to do this? I have researched quite a bit about this and I am thinking on going back to a previous version of the library where I could just use the old way.
Edit: Just to clarify the problem doesn't have anything to do with the labels, but with the start and end of the Chart in X, it is discarding the range of X which doesn't have any YValues which I understand makes sense but it makes the results look ugly in certain cases.
You can use the setLabelCount() method to force the axis to draw labels according to the count you specify
According to the documentation:
setLabelCount(int count, boolean force)
#param count: the number of y-axis labels that should be displayed
#param force if enabled, the set label count will be forced, meaning that the exact specified count of labels will be drawn and evenly distributed alongside the axis - this might cause labels to have uneven values
And the setLabelCount method is defined below
public void setLabelCount(int count) {
if (count > 25)
count = 25;
if (count < 2)
count = 2;
mLabelCount = count;
mForceLabels = false;
}
You can use setLabelCount() with setAxisMaximum() and setAxisMinimum()
For example:
axis.setLabelCount(24, true);
axis.setAxisMaximum(24f);
axis.setAxisMinimum(0f);
This will draw values from 0 - 24 regardless of Y-Axis values
I am facing a strange issue with ShinobiCharts[Android] column width for the below scenarios:
XAxis : Date <br>
YAxis : Double
Input 1: DataAdapter= {[00:00,0.0], [02:00,360] , [24:00,0.0] }
Output : below output#1 screenshot shows expected column width wit bar.
Input 2: DataAdapter={[00,0.0], [15:150.0], [24:00,0.0]}
Output : screenshot 2 shows a bar with more length of column which does not fit inside that bounds.
Input 3: DataAdapter={[00,0.0], [23:00,360.0] , [24:00,0.0]}
Output : screenshot 3 shows even bigger and bigger and column width.
If adapter all has 3 entries for that day, then every column width showed like screenshot 1.
Question is: I just wanted to know what am i missing here, and what api should I use to restrict this column width to shown only inside that bounds where it fits?
Please help me.
private Series createSeries(#NonNull final DataAdapter<Date, Integer> dataAdapter, #NonNull final String title, final int color) {
final ColumnSeries series = new ColumnSeries();
series.setDataAdapter(dataAdapter);
series.setShownInLegend(true);
series.setTitle(title);
series.setSelectionMode(Series.SelectionMode.POINT_MULTIPLE);
ColumnSeriesStyle style = series.getStyle();
style.setAreaColor(color);
style.setAreaColorGradient(color);
style.setLineColor(color);
series.setStackId(1);
return series;
}
Here is the solution to my own question.
Problem:
shinoby-version: shinobicharts-android-premium-1.7.2-0.jar
from the below link , got to know that shinobycharts does not have api to control the width of the column (vertical bar) (scroll down and see (rippling posted this 22 January 2016)) its backlog item .
[shinobicontrols.com/forum/shinobicontrols/2013/4/how-are-the-widths-of-columns-set]
as per the attached screenshots, if there is no entry point for the first partition midnight 12- to early morning 4 [12-4] or [00-04] per a day on X-axis, the width of the column is uncontrollable.
Solution:
As a workaround or a proper fix, I just added a dummy entry in the first partition if there is no actual data. and the final adapter looks like below.
If actual data presents for the 1st partition i.e [12-4] in screenshot. no need to add dummy here:
earlier: DataAdapter= {[00:00,0.0],[02:00,360],[24:00,0.0] }
now: DataAdapter= {[00:00,0.0],[02:00,360],[24:00,0.0] }
//no change as it was earlier.
if not:
earlier: DataAdapter={[00,0.0], [15:150.0], [24:00,0.0]}
now: DataAdapter= {[00:00,0.0],[02:00,0],[15:150.0],[24:00,0.0] }
end entry [02:00, 0] is the dummy entry here. and does not mess up the output as the VALUE is set to Zero here.
Output:#
Without entry in the first partition 12-4
With entry in the first partition 12-4
I am glad that you were able to resolve your issue.
As you have seen, the data itself can have a significant impact on the width at which the columns are drawn.
When the chart calculates the width at which to draw the column, amongst other things it looks at the distance between each data value for the relevant axis. It will choose the shortest distance between two data point values and base it’s column width calculation on this. This approach usually results in evenly spaced columns with a consistent width, except when the data point values have a varied frequency. For example if most of your data points have an x value 9 hours from it’s adjacent ones, but then one pair of x values are only 2 hours apart, you may experience this type of issue. Furthermore, a DateTime axis, when used with a column or bar chart can also result in varying column or bar widths because date frequencies are often varied. For example, for monthly data, some months have 31 days whereas some have 30, 28 or 29.
In the future we may look to provide additional api methods to allow manual setting of column width. I cannot of course give any firm indication of when such api will be available. In the meantime if you still experience issues with your column chart, please do get in touch by contacting info#shinobicontrols.com. In this instance please do include a code sample where possible, to help us to get up to speed with your issue quickly.
Thanks and kind regards,
Kai
Disclaimer: I work for Shinobicontrols.
This question has been made here, but still has got no answer...
Using StackedBarActivity example from MPAndroidChart library to draw a 3 merge bars, and setting the values as [1,2,3]... the chart is showed with a total of all numbers, 1+2+3=6.. but what I want is to merge all values in order to value 2 overlay value 3 and value 1 overlay value 2, as showed on the image bellow:
Basically, I want to use the StackedBarActivity activity, but not stack all the bars, instead, I want to put one behind another.
Visually I know I can subtract the bigger value with the smaller, making a sum until reaching 3 (1+1+1), but then the value 3 will retain value 1 and not value 3.
Is there a way I can do this using this class? Is there a better class to do this?
I know I am like 6 months late with answer, but I think that is working solution:
List<String> xVals = getXVals(); //some function to get values
List<BarEntry> yVals = new ArrayList();
int[] barColors = new int[bars.size() * numberOfValues];
int index=0;
for (Bar bar : bars) {
List<BarEntry> yValsForBar = new ArrayList();
for (int i=0; i<numberOfValues; i++) {
yValsForBar.add(new BarEntry(bar.value(i), i));
barColors[i+index*numberOfValues] = bar.color();
}
yVals.addAll(yValsForBar);
index++;
}
BarDataSet dataSet = new BarDataSet(yVals, "data set");
BarData data = new BarData(xVals);
data.addDataSet(dataSet);
And here, you should have overlying bars in different colors (note: of course you might not see some bars if they have bigger values than next ones, if you wan't to sort them you will have to do some modifications to this). At least works with me.
Expanding on n4yArh's answer.
With the latest version of the library, the constructor for BarEntry has changed to BarEntry(x,y).
So the line
yValsForBar.add(new BarEntry(bar.value(i),i));
should be changed to
yValsForBar.add(new BarEntry(i,bar.value(i));
and of course to use the color array, the following line is missing
dataSet.setColors(barColors);
I'ms setting custom text labels on my line chart, using this on the renderer:
String[] xLabelsForTimeScale = getXLabelsForCurrentTimeScale(); //weekday names
for (int i = 0; i < xLabelsForTimeScale.length; i++)
{
mRenderer.addXTextLabel(i, xLabelsForTimeScale[i]);
}
mRenderer.setXLabels(0);
mRenderer.setShowCustomTextGridX(true);
when the chart renders, it's only displaying x labels for points where I have a non null series value. For example, assume that the xLabelsForTimeScale array is an array of weekday abbreviations. If I have only two values, say for Mon, Tue, it only shows labels for Mon and Tue. I'd like to display all the x axis labels, whether there's a series point or not. Sun - Sat, basically. How can I do that?
ADDITIONAL INFO ON REQUIREMENT: I don't want to add zero, dummy points within the series if I can at all help it. What I expect to happen is the line just renders between actual points, connecting each actual, valid point, in a linear fashion. If I add zero, dummy points, there will be a lot of pointy tops (lack of a better term) as the line draws between valid point data, and placeholder, dummy data. Hope that makes sense. Thanks.
You can avoid this for time charts by calling:
renderer.setXRoundedLabels(false);
I'm using achartengine in my Android Application, it works well but i have a question.
Is it possible to reverse plot?
I mean in my graph, new values which are added to my XY series with the function add, are added at end of the series, and then the graph is redrawn, so new values appears at right of the graph.
But i want to add my new value at index 0, in order to show on the graph only the last X values.
Sorry if it's not very clear
Thanks
There is no support for inserting data to XYSeries at a given index. However you could get to this behavior by clearing the current data and adding it back, with the new value included. I know this would not be a very optimal way, but it helps you get to your needed behavior.
Edit: I added an add(index, x, y) method in XYSeries. You can download a version including this feature here.
So, i've found a trick:
Dataset is my XYseries and mRenderer my multipleSeriesRenderer
I've changed alignment of the Y axis:
mRenderer.setYAxisAlign(Align.RIGHT, 0);
I've erased automatic labels:
mRenderer.setXLabels(0);
The 0 on the axe X is now a custom label, so every time a new value is added to the graph, I have to change is position:
mRenderer.setXAxisMax(dataset.getItemCount() - 1); mRenderer.addXTextLabel(dataset.getItemCount() - 1, "0");
And to finish, i change the X axis min everytime a new value is added, in order to get a fix scale:
mRenderer.setXAxisMin(dataset.getItemCount() - scale - 1);