强制 BarChart Y 轴标签为整数?
Force BarChart Y axis labels to be integers?
我已经使用 MPAndroidChart 创建了一个条形图,并且正在动态输入数据。这意味着我还需要动态确定 Y 轴。我的所有数据都表示为整数,但是 Y 轴有时将图例显示为带 1 个小数点的十进制值。
我尝试使用 ValueFormatter 对值进行舍入,但问题是有时 Y 值不在整数值位置(例如 0.8、1.6、2.4 等)。因此,如果我只是将它们编辑为整数,它们将不会位于正确的位置。
有没有办法强制条形图只显示整数位置的值?如果它跳过一些也没关系,事实上我希望它在值变大时跳过。
编辑:当我说整数不在正确的位置时,我的意思是一旦我修改了每个标签显示的内容,它们就不是 'correct'。在我的示例中,我有 5 个条形图显示值 3、4、2、3、2。第一张图片是 'default',第二张图片是我使用
编辑值格式化程序后的图片
myBarChart.getYLabels().setFormatter(new ValueFormatter()
{
@Override
public String getFormattedValue(float v)
{
return ((int) v)+"";
}
});
正如我们从这些图像中看到的那样,我的整数值不在应有的位置(并且有两个“2”)。在这个例子中,我将它排除在外,以显示值 0、1、2、3、4。如果我有更多的数据,我希望它足够聪明,只显示我有空间的值,例如,如果数据包含 0-50 的值,它会显示类似 0,10,20,30 的内容,40,50 或可能是 0,15,30,45 等
好的,现在我明白你的问题了。
问题是 YAxis
(YLabels) 确定位数,因此每个标签之间的步数 自动 。
遗憾的是,目前无法自定义轴如何自行计算或设置自定义标签。
我正在考虑将来添加这样的功能,用户可以在其中自定义绘制哪些值作为轴标签。
提示一下:
包含所有轴标签的 mEntries
数组是 public。所以一般来说,您可以在创建后对其进行修改。
但是,我完全不确定如果手动修改轴将如何表现。
很简单。您只需要两件事:
轴值格式化程序
mChart.getAxisLeft().setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
return String.valueOf((int) Math.floor(value));
}
});
轴标签数
int max = findMaxYValue(yourdata); // figure out the max value in your dataset
mChart.getAxisLeft().setLabelCount(max);
我就是这样解决这个问题的。似乎 y 轴总是在最大值之上绘制 1(如果它不强制它)。因此,将标签计数 2 设置为大于最大值(包括零和最大值),然后您需要做的就是使用轴格式化程序删除小数点。如果您的所有 y 值都是整数,则此方法有效,但不确定它如何处理小数值。
barChart.getAxisLeft().setLabelCount(maxYvalue + 2, true);
barChart.getAxisLeft().setAxisMinValue(0f);
barChart.getAxisLeft().setAxisMaxValue(maxYvalue + 1);
YAxisValueFormatter customYaxisFormatter = new YAxisValueFormatter() {
@Override
public String getFormattedValue(float value, YAxis yAxis) {
return String.valueOf((int)value);
}
};
barChart.getAxisLeft().setValueFormatter(customYaxisFormatter);
我知道我回答的很晚了,但我正在尝试对这个问题进行更多说明,以便未来的用户对此有更多的了解。
我也遇到了同样的问题。我使用 MyYAxisValueFormatter
只显示 Y-Axis
中的整数值。下面是相同的代码。
public class MyYAxisValueFormatter implements YAxisValueFormatter {
private DecimalFormat mFormat;
public MyYAxisValueFormatter () {
mFormat = new DecimalFormat("###,###,##0");
}
@Override
public String getFormattedValue(float value, YAxis yAxis) {
// write your logic here
// access the YAxis object to get more information
return mFormat.format(value);
}
}
通过使用这个 class 发生的事情肯定是它以整数格式显示 Y 轴值,但也复制了一些值。那是因为将浮点值转换为整数。
Let say for example 0.4 will be converted to 0 so there will be two or
may be more 0 values in Y-Axis.
我认为这就是 @Fozefy
的情况。
我在下面实现了给定的代码来解决这个问题,它的工作非常棒。我使用 setAxisMaxValue
函数为 Y 轴设置自定义最大值,并使用 setLabelCount
为 Y 轴设置标签条目数。
YAxis yAxis = chart.getAxis(YAxis.AxisDependency.LEFT);
// Minimum section is 1.0f, could be 0.25f for float values
float labelInterval = 1.0f / 2f;
int sections; //No of sections in Y-Axis, Means your Highest Y-value.
do {
labelInterval *= 2; //Interval between labels in Y-Axis
sections = ((int) Math.ceil(chart.getYMax() / labelInterval));
} while (sections > 10);
// If the ymax lies on one of the top interval, add another one for some spacing
if (chart.getYMax() == sections * labelInterval) {
sections++;
}
yAxis.setAxisMaximum(labelInterval * sections);
yAxis.setLabelCount(sections + 1, true);
Label interval remains one if your maximum y-value is less than 10
otherwise two. You can customize this behavior as per your requirement
and also increase label interval by modifying do-while loop.
还要确保您正在使用 setLabelCount(int count, boolean force)
方法并将 force
值传递给 true
。
在四处寻找没有可用的解决方案后,我决定查看 javadoc 并找到了这个方法:setGranularity(float)
。要强制 YAxis 始终显示整数(或任何你想要的间隔),你只需要这样调用:
yAxisLeft.setGranularity(1.0f);
yAxisLeft.setGranularityEnabled(true); // Required to enable granularity
但是,如果图表的最小值和最大值太接近,则图表将不会遵循 setLabelCount()
,除非强制执行(这将使标签再次变为十进制),因此您需要在设置数据后调用它:
private void calculateMinMax(BarLineChartBase chart, int labelCount) {
float maxValue = chart.getData().getYMax();
float minValue = chart.getData().getYMin();
if ((maxValue - minValue) < labelCount) {
float diff = labelCount - (maxValue - minValue);
maxValue = maxValue + diff;
chart.getAxisLeft().setAxisMaximum(maxValue);
chart.getAxisLeft().setAxisMinimum(minValue);
}
}
就是这样!
我的解决方案:
mChart.getAxisLeft().setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
return String.valueOf((int) Math.floor(value));
}
});
int max = (int) mChart.getData().getYMax();
mChart.getAxisLeft().setLabelCount(max);
这是一个简单的解决方案,可以帮助正在寻找答案的人。
Y 轴标签数
barChart.getAxisLeft().setLabelCount(7, true); //if you want 6 labels then value should be 7
计算maxValue
- 从需要包含在图表中的值中获取
maxValue
int maxValueMod = (maxValue + 2) % 6; //calc mod, here 2 is to display Legend and 6 is no of labels
maxValue = maxValue + (6-maxValueMod); // calculate final maxValue to set in barchart
barChart.getAxisLeft().setAxisMaximum(maxValue+2); ```
要添加到解决方案中,如果有人只想删除小数和重复值,您可以这样做:
IAxisValueFormatter yAxisValueFormatter = new IAxisValueFormatter() {
@Override
public String getFormattedValue(float v, AxisBase axisBase) {
//check for decimal value
if (v - (int) v != 0) {
return "";
} else {
return String.valueOf((int) v);
}
}
};
leftAxis.setValueFormatter(yAxisValueFormatter);
rightAxis.setValueFormatter(yAxisValueFormatter);
我遇到了同样的问题,我正在获取:
要仅显示“整数”(在本例中为“10”),试试这个:
chart.axisLeft.valueFormatter = object : ValueFormatter() {
override fun getFormattedValue(value: Float): String {
return if (value == value.toInt().toFloat()) {
(floor(value.toDouble()).toInt()).toString()
} else {
""
}
}
}
结果:
值参数的每次更改和显示都会导致误导性标签。
为此,您需要适当地设置 AxisMinimum()、setAxisMaximum()、setGranularity() 和 setLabelCount(),然后只显示您想要的标签。
比如要显示秒数,可以这样设置这些参数:
YAxis yAxis = chartName.getAxisLeft();
yAxis.setAxisMinimum(0);//start from 0am
yAxis.setAxisMaximum(86400);//seconds of day
yAxis.setGranularityEnabled(true);
yAxis.setGranularity(1);//values interval
yAxis.setLabelCount(25, true);//from 0 to 24
这会将 ValueFormatter 中的值参数设置为 25 个部分,这将是相等的,因此当您除以 3600 得到小时时,它将是偶数。
chartNmae.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
Log.i("Y axis: ", value / 3600 + "h");
int hour = (int)value / 3600;
//if you only want to show some of the values/labels then filter them
return hour % 2 == 0 ? hour + ":00" : "";//return even hour or make the label empty
}
Logcat:
Y axis:: 0.0h
Y axis:: 1.0h
Y axis:: 2.0h
Y axis:: 3.0h
Y axis:: 4.0h
Y axis:: 5.0h
Y axis:: 6.0h
Y axis:: 7.0h
Y axis:: 8.0h
Y axis:: 9.0h
Y axis:: 10.0h
Y axis:: 11.0h
Y axis:: 12.0h
Y axis:: 13.0h
Y axis:: 14.0h
Y axis:: 15.0h
Y axis:: 16.0h
Y axis:: 17.0h
Y axis:: 18.0h
Y axis:: 19.0h
Y axis:: 20.0h
Y axis:: 21.0h
Y axis:: 22.0h
Y axis:: 23.0h
Y axis:: 24.0h
您在图表中的 values/entries 是相同的并且可能是浮动的,但标签将是整数并且将设置在正确的位置。因此,如果数据集中的条目是 36600 (10:10am),它应该出现在 10:00am.
上方的 1/6 处
但是,如果我们将轴最大值稍微更改为 setAxisMaximum(86000),则 ValueFormatter 将传递小数点后带分数的参数。我们仍然可以通过将 ValueFormatter 参数(值)四舍五入并将其 return 作为标签来获得均匀的 lebel,但与其关联的值将略微显示在下面,现在 10:10am(36600 数据集条目)将出现在旁边10:00 标签(不是它上面的 1/6),因为我们将标签的实际值向下舍入,但将其显示在轴上的保留位置。这就像将您的手表拨慢 10 分钟并查看它。它可能显示 10:00am 但实际上是 10:10am.
Logcat:
Y axis:: 0.0h
Y axis:: 0.9953703h
Y axis:: 1.9907407h
Y axis:: 2.9861112h
Y axis:: 3.9814813h
Y axis:: 4.9768515h
Y axis:: 5.9722223h
Y axis:: 6.9675927h
Y axis:: 7.962963h
Y axis:: 8.958334h
Y axis:: 9.953705h
Y axis:: 10.949075h
Y axis:: 11.944445h
Y axis:: 12.939815h
Y axis:: 13.9351845h
Y axis:: 14.930554h
Y axis:: 15.925924h
Y axis:: 16.921295h
Y axis:: 17.916664h
Y axis:: 18.912035h
Y axis:: 19.907406h
Y axis:: 20.902779h
Y axis:: 21.89815h
Y axis:: 22.89352h
Y axis:: 23.888891h
如果我们将最大值更改为 setAxisMaximum (60000),事情就会变得非常混乱:
Logcat:
Y axis:: 0.0h
Y axis:: 0.6944444h
Y axis:: 1.3888888h
Y axis:: 2.0833333h
Y axis:: 2.7777777h
Y axis:: 3.4722223h
Y axis:: 4.1666665h
Y axis:: 4.861111h
Y axis:: 5.5555553h
Y axis:: 6.25h
Y axis:: 6.9444447h
Y axis:: 7.638889h
Y axis:: 8.333333h
Y axis:: 9.027778h
Y axis:: 9.722222h
Y axis:: 10.416667h
Y axis:: 11.111111h
Y axis:: 11.805555h
Y axis:: 12.5h
Y axis:: 13.194445h
Y axis:: 13.888889h
Y axis:: 14.583333h
Y axis:: 15.277778h
Y axis:: 15.972222h
Y axis:: 16.666666h
我已经使用 MPAndroidChart 创建了一个条形图,并且正在动态输入数据。这意味着我还需要动态确定 Y 轴。我的所有数据都表示为整数,但是 Y 轴有时将图例显示为带 1 个小数点的十进制值。
我尝试使用 ValueFormatter 对值进行舍入,但问题是有时 Y 值不在整数值位置(例如 0.8、1.6、2.4 等)。因此,如果我只是将它们编辑为整数,它们将不会位于正确的位置。
有没有办法强制条形图只显示整数位置的值?如果它跳过一些也没关系,事实上我希望它在值变大时跳过。
编辑:当我说整数不在正确的位置时,我的意思是一旦我修改了每个标签显示的内容,它们就不是 'correct'。在我的示例中,我有 5 个条形图显示值 3、4、2、3、2。第一张图片是 'default',第二张图片是我使用
编辑值格式化程序后的图片myBarChart.getYLabels().setFormatter(new ValueFormatter()
{
@Override
public String getFormattedValue(float v)
{
return ((int) v)+"";
}
});
正如我们从这些图像中看到的那样,我的整数值不在应有的位置(并且有两个“2”)。在这个例子中,我将它排除在外,以显示值 0、1、2、3、4。如果我有更多的数据,我希望它足够聪明,只显示我有空间的值,例如,如果数据包含 0-50 的值,它会显示类似 0,10,20,30 的内容,40,50 或可能是 0,15,30,45 等
好的,现在我明白你的问题了。
问题是 YAxis
(YLabels) 确定位数,因此每个标签之间的步数 自动 。
遗憾的是,目前无法自定义轴如何自行计算或设置自定义标签。
我正在考虑将来添加这样的功能,用户可以在其中自定义绘制哪些值作为轴标签。
提示一下:
包含所有轴标签的 mEntries
数组是 public。所以一般来说,您可以在创建后对其进行修改。
但是,我完全不确定如果手动修改轴将如何表现。
很简单。您只需要两件事:
轴值格式化程序
mChart.getAxisLeft().setValueFormatter(new ValueFormatter() { @Override public String getFormattedValue(float value) { return String.valueOf((int) Math.floor(value)); } });
轴标签数
int max = findMaxYValue(yourdata); // figure out the max value in your dataset mChart.getAxisLeft().setLabelCount(max);
我就是这样解决这个问题的。似乎 y 轴总是在最大值之上绘制 1(如果它不强制它)。因此,将标签计数 2 设置为大于最大值(包括零和最大值),然后您需要做的就是使用轴格式化程序删除小数点。如果您的所有 y 值都是整数,则此方法有效,但不确定它如何处理小数值。
barChart.getAxisLeft().setLabelCount(maxYvalue + 2, true);
barChart.getAxisLeft().setAxisMinValue(0f);
barChart.getAxisLeft().setAxisMaxValue(maxYvalue + 1);
YAxisValueFormatter customYaxisFormatter = new YAxisValueFormatter() {
@Override
public String getFormattedValue(float value, YAxis yAxis) {
return String.valueOf((int)value);
}
};
barChart.getAxisLeft().setValueFormatter(customYaxisFormatter);
我知道我回答的很晚了,但我正在尝试对这个问题进行更多说明,以便未来的用户对此有更多的了解。
我也遇到了同样的问题。我使用 MyYAxisValueFormatter
只显示 Y-Axis
中的整数值。下面是相同的代码。
public class MyYAxisValueFormatter implements YAxisValueFormatter {
private DecimalFormat mFormat;
public MyYAxisValueFormatter () {
mFormat = new DecimalFormat("###,###,##0");
}
@Override
public String getFormattedValue(float value, YAxis yAxis) {
// write your logic here
// access the YAxis object to get more information
return mFormat.format(value);
}
}
通过使用这个 class 发生的事情肯定是它以整数格式显示 Y 轴值,但也复制了一些值。那是因为将浮点值转换为整数。
Let say for example 0.4 will be converted to 0 so there will be two or may be more 0 values in Y-Axis.
我认为这就是 @Fozefy
的情况。
我在下面实现了给定的代码来解决这个问题,它的工作非常棒。我使用 setAxisMaxValue
函数为 Y 轴设置自定义最大值,并使用 setLabelCount
为 Y 轴设置标签条目数。
YAxis yAxis = chart.getAxis(YAxis.AxisDependency.LEFT);
// Minimum section is 1.0f, could be 0.25f for float values
float labelInterval = 1.0f / 2f;
int sections; //No of sections in Y-Axis, Means your Highest Y-value.
do {
labelInterval *= 2; //Interval between labels in Y-Axis
sections = ((int) Math.ceil(chart.getYMax() / labelInterval));
} while (sections > 10);
// If the ymax lies on one of the top interval, add another one for some spacing
if (chart.getYMax() == sections * labelInterval) {
sections++;
}
yAxis.setAxisMaximum(labelInterval * sections);
yAxis.setLabelCount(sections + 1, true);
Label interval remains one if your maximum y-value is less than 10 otherwise two. You can customize this behavior as per your requirement and also increase label interval by modifying do-while loop.
还要确保您正在使用 setLabelCount(int count, boolean force)
方法并将 force
值传递给 true
。
在四处寻找没有可用的解决方案后,我决定查看 javadoc 并找到了这个方法:setGranularity(float)
。要强制 YAxis 始终显示整数(或任何你想要的间隔),你只需要这样调用:
yAxisLeft.setGranularity(1.0f);
yAxisLeft.setGranularityEnabled(true); // Required to enable granularity
但是,如果图表的最小值和最大值太接近,则图表将不会遵循 setLabelCount()
,除非强制执行(这将使标签再次变为十进制),因此您需要在设置数据后调用它:
private void calculateMinMax(BarLineChartBase chart, int labelCount) {
float maxValue = chart.getData().getYMax();
float minValue = chart.getData().getYMin();
if ((maxValue - minValue) < labelCount) {
float diff = labelCount - (maxValue - minValue);
maxValue = maxValue + diff;
chart.getAxisLeft().setAxisMaximum(maxValue);
chart.getAxisLeft().setAxisMinimum(minValue);
}
}
就是这样!
我的解决方案:
mChart.getAxisLeft().setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
return String.valueOf((int) Math.floor(value));
}
});
int max = (int) mChart.getData().getYMax();
mChart.getAxisLeft().setLabelCount(max);
这是一个简单的解决方案,可以帮助正在寻找答案的人。
Y 轴标签数
barChart.getAxisLeft().setLabelCount(7, true); //if you want 6 labels then value should be 7
计算
maxValue
- 从需要包含在图表中的值中获取
maxValue
int maxValueMod = (maxValue + 2) % 6; //calc mod, here 2 is to display Legend and 6 is no of labels maxValue = maxValue + (6-maxValueMod); // calculate final maxValue to set in barchart barChart.getAxisLeft().setAxisMaximum(maxValue+2); ```
- 从需要包含在图表中的值中获取
要添加到解决方案中,如果有人只想删除小数和重复值,您可以这样做:
IAxisValueFormatter yAxisValueFormatter = new IAxisValueFormatter() {
@Override
public String getFormattedValue(float v, AxisBase axisBase) {
//check for decimal value
if (v - (int) v != 0) {
return "";
} else {
return String.valueOf((int) v);
}
}
};
leftAxis.setValueFormatter(yAxisValueFormatter);
rightAxis.setValueFormatter(yAxisValueFormatter);
我遇到了同样的问题,我正在获取:
要仅显示“整数”(在本例中为“10”),试试这个:
chart.axisLeft.valueFormatter = object : ValueFormatter() {
override fun getFormattedValue(value: Float): String {
return if (value == value.toInt().toFloat()) {
(floor(value.toDouble()).toInt()).toString()
} else {
""
}
}
}
结果:
值参数的每次更改和显示都会导致误导性标签。 为此,您需要适当地设置 AxisMinimum()、setAxisMaximum()、setGranularity() 和 setLabelCount(),然后只显示您想要的标签。
比如要显示秒数,可以这样设置这些参数:
YAxis yAxis = chartName.getAxisLeft();
yAxis.setAxisMinimum(0);//start from 0am
yAxis.setAxisMaximum(86400);//seconds of day
yAxis.setGranularityEnabled(true);
yAxis.setGranularity(1);//values interval
yAxis.setLabelCount(25, true);//from 0 to 24
这会将 ValueFormatter 中的值参数设置为 25 个部分,这将是相等的,因此当您除以 3600 得到小时时,它将是偶数。
chartNmae.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
Log.i("Y axis: ", value / 3600 + "h");
int hour = (int)value / 3600;
//if you only want to show some of the values/labels then filter them
return hour % 2 == 0 ? hour + ":00" : "";//return even hour or make the label empty
}
Logcat:
Y axis:: 0.0h
Y axis:: 1.0h
Y axis:: 2.0h
Y axis:: 3.0h
Y axis:: 4.0h
Y axis:: 5.0h
Y axis:: 6.0h
Y axis:: 7.0h
Y axis:: 8.0h
Y axis:: 9.0h
Y axis:: 10.0h
Y axis:: 11.0h
Y axis:: 12.0h
Y axis:: 13.0h
Y axis:: 14.0h
Y axis:: 15.0h
Y axis:: 16.0h
Y axis:: 17.0h
Y axis:: 18.0h
Y axis:: 19.0h
Y axis:: 20.0h
Y axis:: 21.0h
Y axis:: 22.0h
Y axis:: 23.0h
Y axis:: 24.0h
您在图表中的 values/entries 是相同的并且可能是浮动的,但标签将是整数并且将设置在正确的位置。因此,如果数据集中的条目是 36600 (10:10am),它应该出现在 10:00am.
上方的 1/6 处但是,如果我们将轴最大值稍微更改为 setAxisMaximum(86000),则 ValueFormatter 将传递小数点后带分数的参数。我们仍然可以通过将 ValueFormatter 参数(值)四舍五入并将其 return 作为标签来获得均匀的 lebel,但与其关联的值将略微显示在下面,现在 10:10am(36600 数据集条目)将出现在旁边10:00 标签(不是它上面的 1/6),因为我们将标签的实际值向下舍入,但将其显示在轴上的保留位置。这就像将您的手表拨慢 10 分钟并查看它。它可能显示 10:00am 但实际上是 10:10am.
Logcat:
Y axis:: 0.0h
Y axis:: 0.9953703h
Y axis:: 1.9907407h
Y axis:: 2.9861112h
Y axis:: 3.9814813h
Y axis:: 4.9768515h
Y axis:: 5.9722223h
Y axis:: 6.9675927h
Y axis:: 7.962963h
Y axis:: 8.958334h
Y axis:: 9.953705h
Y axis:: 10.949075h
Y axis:: 11.944445h
Y axis:: 12.939815h
Y axis:: 13.9351845h
Y axis:: 14.930554h
Y axis:: 15.925924h
Y axis:: 16.921295h
Y axis:: 17.916664h
Y axis:: 18.912035h
Y axis:: 19.907406h
Y axis:: 20.902779h
Y axis:: 21.89815h
Y axis:: 22.89352h
Y axis:: 23.888891h
如果我们将最大值更改为 setAxisMaximum (60000),事情就会变得非常混乱:
Logcat:
Y axis:: 0.0h
Y axis:: 0.6944444h
Y axis:: 1.3888888h
Y axis:: 2.0833333h
Y axis:: 2.7777777h
Y axis:: 3.4722223h
Y axis:: 4.1666665h
Y axis:: 4.861111h
Y axis:: 5.5555553h
Y axis:: 6.25h
Y axis:: 6.9444447h
Y axis:: 7.638889h
Y axis:: 8.333333h
Y axis:: 9.027778h
Y axis:: 9.722222h
Y axis:: 10.416667h
Y axis:: 11.111111h
Y axis:: 11.805555h
Y axis:: 12.5h
Y axis:: 13.194445h
Y axis:: 13.888889h
Y axis:: 14.583333h
Y axis:: 15.277778h
Y axis:: 15.972222h
Y axis:: 16.666666h