强制 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。所以一般来说,您可以在创建后对其进行修改。 但是,我完全不确定如果手动修改轴将如何表现。

但也许值得一试:-) https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java

很简单。您只需要两件事:

  1. 轴值格式化程序

    mChart.getAxisLeft().setValueFormatter(new ValueFormatter() {
        @Override
        public String getFormattedValue(float value) {
            return String.valueOf((int) Math.floor(value));
        }
    });
    
  2. 轴标签数

    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);

这是一个简单的解决方案,可以帮助正在寻找答案的人。

  1. Y 轴标签数

    barChart.getAxisLeft().setLabelCount(7, true); //if you want 6 labels then value should be 7

  2. 计算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