Charts: Остановить дублирование меток осей.

Созданный на 24 авг. 2015  ·  51Комментарии  ·  Источник: danielgindi/Charts

В приложении у меня возникла проблема, когда метки на левой оси либо BarChartView , либо LineChartView повторяются.

Сначала я добавил приведенный ниже фрагмент, чтобы количество меток на оси не превышало максимальное значение в данных y.

self.chartView.leftAxis.labelCount = self.chartView.data.yMax > YAxisMaxLabelCount ? YAxisMaxLabelCount : self.chartView.data.yMax;

Это гарантировало, что если максимальное значение в данных y равно 3 , то на оси будет только 3 меток. Теперь это работало нормально, если график не был интерактивным, т.е. пользователь не мог масштабировать график.

Очевидно, что как только пользователь увеличивает масштаб, количество меток остается прежним, а средство форматирования значений заполняет промежутки, позволяя повторять значение.

_Пример оси без повторяющихся значений_
screen shot 2015-08-24 at 5 07 29 pm

_Пример того же графика, но увеличенного_
screen shot 2015-08-24 at 5 07 54 pm

Скриншоты показывают, что левая ось повторяет значение 2 . Каково ваше лучшее предложение по решению этой проблемы с повторяющимися ярлыками? Любая помощь будет признательна. Если вам нужна дополнительная информация, дайте мне знать.

Спасибо

Самый полезный комментарий

Это выпущено в версии 2.2.4 как функция granularity

Все 51 Комментарий

Я предполагаю, что это не метка дублируется, а содержит десятичные значения и средство форматирования целых чисел? Вам нужно проверить, какое исходное значение для каждой метки оси x и как вы его форматируете, когда он рисует метки оси x в средстве визуализации оси y.

Я смог сделать это, добавив проверку, чтобы гарантировать, что интервал каждой метки всегда является целым значением.
Изменение находится внутри функции computeAxisValues() класса ChartYAxisRenderer

var interval = ChartUtils.roundToNextSignificant(number: Double(rawInterval))
if(_yAxis.valueFormatter?.maximumFractionDigits == 0)
{
    interval = interval < 1 ? 1 : floor(interval)
}

Если средство форматирования значений запрашивает, чтобы не было цифр дробной части, то оно сокращает интервалы, а если оно меньше целого числа 1 , оно устанавливает интервал равным 1 .

Хотите запрос на вытягивание?

Спасибо за вашу помощь.

Если у вас есть десятичные значения, почему maxFractionDigits равен 0? Думаю дело в форматтере.

Мне не нужны десятичные значения, поэтому я установил maximumFractionDigits = 0

дружище, у тебя данные десятичные, и ты просто хочешь с помощью форматтера отказаться от цифр дроби, смысла нет. Почему бы сначала не преобразовать ваши данные в целые числа?

Значения y, которые я даю диаграмме,

(1, 3, 2, 0, 0, 7, 0)

Как только я создаю ChartDataSet , эти значения удваиваются.

ChartDataSet, label: , 7 entries:
ChartDataEntry, xIndex: 0, value 1.0
ChartDataEntry, xIndex: 1, value 3.0
ChartDataEntry, xIndex: 2, value 2.0
ChartDataEntry, xIndex: 3, value 0.0
ChartDataEntry, xIndex: 4, value 0.0
ChartDataEntry, xIndex: 5, value 7.0
ChartDataEntry, xIndex: 6, value 0.0

Это связано с тем, что ваш класс ChartDataEntry содержит значение как Double

/// the actual value (y axis)
public var value = Double(0.0)

Хотя значения были изменены на двойные, диаграммы сначала показывают правильное приращение меток, но как только диаграмма увеличивается, ChartYAxisRenderer хочет заполнить пробелы, и поскольку мой форматировщик значений удалил все дробные цифры он показывает как повторяющееся значение.

Я не хочу, чтобы диаграмма предполагала, что мне нужны дополнительные значения между целыми числами, поскольку я хочу показать метку только для целого числа.

Итак, это приводит меня к выводу, что я предоставляю правильные данные для диаграммы, но диаграмма делает предположения о том, что я хочу сделать. Это нормально для значения по умолчанию, но также должно предоставлять возможность отображать только целые числа на оси.

Добавление проверки форматирования значения позволяет такое поведение. Возможно, вы знаете лучший способ обеспечить это поведение, а не проверять средство форматирования значений, но это вариант использования, который некоторые люди хотят.

Я только что заметил, что использую базу кода при фиксации a7e30dd16fbfaecb8e44c01ad8618a3a745fd101, и когда это изменение реализовано в последней фиксации Charts, оно не работает должным образом.

Не могли бы вы посоветовать, как лучше всего добиться желаемого поведения?

Я прикрепил gif ожидаемого поведения.

Ниже вы можете видеть, что ни одна метка не показывает одинаковое значение, и диаграмма не пытается разместить какую-либо метку между другими метками, поскольку существует требование, чтобы метки были целыми значениями.

chart

Ах я вижу. Если вы увеличите масштаб, скажем, до [3,4], диапазон будет равен [3,4], а ось будет отображать [3,0, 3,2, 3,4, 3,6, 3,8, 4,0], и вам не нужны дробные числа, это?

На самом деле я ничего не могу сделать... так как ваши данные довольно малы, и мы должны отобразить там 4-6 меток... А если диапазон [0,1], и вам нужно отобразить 5 меток, что может вы отображаете кроме дробных цифр?

Я думаю, что можно отображать дробные числа, если диапазон слишком мал, но если вы действительно этого не хотите, вы можете сделать это так, как сделали. Или вы согласитесь показывать только максимальную и минимальную метку с именем showOnlyMinMaxEnabled

Кстати, ваши скриншоты отлично работают, проблема решена.

Есть также некоторые свойства, которые помогут вам ограничить количество меток. Вы можете попробовать изменить и подогнать для разных уровней масштаба.

    public func setLabelCount(count: Int, force: Bool)
    {
        _labelCount = count

        if (_labelCount > 25)
        {
            _labelCount = 25
        }
        if (_labelCount < 2)
        {
            _labelCount = 2
        }

        forceLabelsEnabled = force
    }

Чтобы иметь такое же поведение по оси Y, необходимо установить предел масштабирования Y. #382

388

@steprescott , #388 решил твою проблему?

Если посмотреть на фиксацию для проблемы № 388, единственное изменение — это новое свойство в окне просмотра.

Как мне получить предполагаемое поведение, показанное на картинке, но с вашими изменениями?

Привет @steprescott , попробуйте с [_chartView.viewPortHandler setMaximumScaleY: 2.f]; например, здесь степень детализации масштабирования не настолько велика, чтобы отображались повторяющиеся значения. Хороший пример: когда у вас есть горизонтальная линия char без ограничений, все значения Y повторяются при большом увеличении. С MaximumScaleY такого повторения не происходит.

Без ограничений:
screen shot 2015-09-22 at 23 29 16

С ограничением 2f:
screen shot 2015-09-22 at 23 30 07

Привет @noais

Это работает с набором данных с более широким диапазоном значений, но если у вас небольшой диапазон значений, например массив значений от 0 до 7, увеличение в 2 раза может потенциально привести к дублированию меток.

Хотя ограничение коэффициента масштабирования решило вашу проблему, оно не решает проблему повторения целых значений.

Я получил ожидаемые результаты при редактировании класса ChartYAxisRenderer , указывающего на коммит a7e30dd16fbfaecb8e44c01ad8618a3a745fd101.

Это было сделано путем установки значения.

var interval = ChartUtils.roundToNextSignificant(number: Double(rawInterval))
if(_yAxis.valueFormatter?.maximumFractionDigits == 0)
{
    interval = interval < 1 ? 1 : floor(interval)
}

Хотя это сработало (но не при использовании HEAD этого репозитория), я чувствую, что вы, ребята, будете знать лучшее место в вашей структуре, чтобы поместить это, чтобы получить тот же результат, что и на картинке.

Может быть, свойство allowRepeatingValues BOOL на оси. Вам, ребята, лучше знать.

Да, вы правы, это был один обходной путь. Позвольте мне попробовать, легко ли создать какой-нибудь метод, например, allowRepeatingValues.

Это было бы очень полезно, спасибо.

Привет @noais и @liuxuan30. У вас была возможность расследовать это? Я смог получить требуемый эффект с помощью фреймворка, но я не знаю, где лучше всего это свойство должно находиться в фреймворке, и есть ли лучший способ добиться того же результата.

Спасибо за ваше время.

Я все еще думаю, что это потому, что форматер создал дублированные метки с маленькими цифрами, а не алгоритм. Если удалить форматер, то он будет правильно отображать номер, да?
Вы можете решить это с помощью своего кода, но я не уверен, что он подходит для всех.
@danielgindi , что ты думаешь

Привет, ребята, голосую за allowRepeatingValues, у меня маленькие числа, и я не хочу отображать повторяющиеся значения по оси Y.

Когда все мои значения равны нулю, я получаю эти повторяющиеся метки осей:
chart

Кроме того, я заметил, что, хотя фрагмент кода, который у меня есть, делает то, что мне нужно, он не удаляет повторяющиеся значения, а просто разрешает целые числа. Таким образом, проверка на средство форматирования чисел не является ужасным способом добавления этого.

Чего этот фрагмент не позволяет, так это удаления повторяющихся значений, поэтому, если значения были 1.1, 1.2, 1.2, 1.3 и вы хотели сохранить одну десятичную цифру, это не сработало бы. Вы, ребята, будете знать лучшее место и реализацию для этой функции, а также для людей, которые будут тратить время на изучение текущих проблем фреймворка, а затем голосовать за них, это показывает, что это вариант, который хотят и другие.

разрешить повторные значения :+1:

@noais @liuxuan30 У вас есть лучшее решение, чем то, что я предложил?

нет, за исключением allowRepeatingValues. Потому что ваша исходная проблема связана с форматировщиками. вам не нужны десятичные цифры на уровне, но ваши данные на самом деле имеют следующий уровень

В идеале график никогда не должен показывать повторяющиеся значения! Можно ли с помощью некоторой логики скрыть повторяющиеся значения, чтобы получить только уникальные значения?

@vigyanhoon это не «повторяющиеся» значения позади, это форматер, который заставляет значение «повторяться». Если вы не хотите повторяться, дайте десятичный форматировщик, который может решить эту проблему.

@ liuxuan30 Можете ли вы объяснить, что вы подразумеваете под «_дайте десятичный форматтер_»? С моими данными я дал средство форматирования, которое установило maximumFractionDigits = 0 . Я не уверен, как получить ожидаемые результаты с тем, что есть в настоящее время? Удалось ли вам создать диаграмму с такой структурой, которая дает те же результаты, что и моя гифка, которую я опубликовал 28 августа?

Вы имели в виду использовать numberFormatter.allowsFloats = NO, если да, то мне это не помогло, я все еще вижу повторяющиеся INT?! Единственный способ, которым мне удалось НЕ отображать повторяющиеся значения, - это использовать 2 метки на xAxis (сверху/снизу).

@steprescott извините, если я не понимаю. MaximumFractionDigits не должен быть равен 0, иначе будет показана только целая часть. Я встречал подобные проблемы, если диапазон данных невелик и требуется 5–6 меток, при задании maxFractionDigits = 0 значения будут повторяться. Я думаю, нет простого способа исправить это. подумайте, если диапазон данных равен [0,2], и мне нужно отобразить 5 меток: 0, 0,4, 0,8, 1,2, 1,6, 2,0. Если мы применим maxFractionDigits = 0, это может быть 0, 0, 1, 1, 2, 2

@injectios , как насчет MaximumFractionDigits = 2 или даже 4?

Всем привет!
У меня такая же проблема.

@ liuxuan30, в зависимости от типа данных, нет смысла использовать десятичные дроби. Как и в таблице людей, у вас никогда не будет 1,5 человека, либо 1, либо 2.

@jpros вы поняли, но с математической точки зрения у нас не может быть 4 меток без десятичных знаков в диапазоне [0,2].

Поэтому либо включите yAxis.showOnlyMinMaxEnabled , чтобы избежать повторяющихся значений в качестве обходного пути на данный момент,
Или вы реализуете свою логику для вычисления собственных значений в ChartYAxisRenderer.computeAxis , чтобы избежать
Или нам нужно дождаться функции «allowRepeatValues»

@PhilJay , у нас есть какое-нибудь решение для этого в настоящее время? :-)

Из POV Android (и iOS) эта строка здесь: https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java#L108

Может быть место для решения этой проблемы. Там вычислены float interval меток осей, и их можно использовать для предотвращения дальнейших изменений меток, если две метки будут отформатированы одинаково.
Это только то, что приходит мне на ум, когда я быстро думаю об этом. Как вы думаете?

Я избавился от дублирования, установив максимальное значение

leftAxis.customAxisMax = maxYLabelCount

@vigyanhoon это совершенно другое, значения могут быть миллионами, а maxYLabelCount - нет. customAxisMax должен определить максимальное значение диапазона оси.

+1 за решение проблемы с рендерингом. У меня также есть график людей, и у меня есть [0, 0, 1, 1, 2, 2]. Установка для numberFormatter.maximumFractionDigits значения, отличного от 0, не имеет никакого смысла.

Следующий код, предложенный @steprescott , также исправлен для меня. Я добавил это в свою вилку здесь:

https://github.com/natanrolnik/ios-charts/commit/01df4d9264e0adbef4db88763075376f4a0f255c

Сможет ли PR закрыть этот вопрос? Что вы думаете @danielgindi @liuxuan30 @steprescott ? Есть ли случаи, когда этот код не исправляет? Если да, то какие решения лучше?

@natanrolnik , что, если пользователь увеличит масштаб и диапазон станет [25.2, 25.3]? Интервал будет равен 1,0, а должен быть, скажем, 0,02.
Это должно помочь, если пользователь специально установил максимальное количество дробей равным 0, мы ограничиваем интервал. Однако я не тестировал отрицательные значения.
У нас пока нет лучшего решения, но я предполагаю, что мы можем придумать такую ​​функцию, как «allowRepeatValues»?

Я согласен относительно allowRepeatedValues !

Я думаю, что @steprescott — хорошее решение. Нужно только настроить значение один на переменную детализации.

С этим @liuxuan30 проблема больше не существует.

Если мы поместим этот код в строку 75 в ChartYAxisRenderer:

interval = interval < granuality ? granuality : interval       

https://github.com/noais/ios-charts/compare/master...Noais
Как вы думаете?

Итак, теперь он закрыт, но не объединен с мастером. Когда это может произойти?

Это выпущено в версии 2.2.4 как функция granularity

Я не уверен, стоит ли мне публиковать этот вопрос здесь, но для меня это имеет смысл.

У меня очень похожая проблема с метками xAxis. У меня есть собственный IAxisValueFormatter, который возвращает строки для времени, он дает такие часы, как «22:00», «23:00» для некоторых диаграмм, дни недели, такие как «Пн», «Чт». для других и т.д..

Когда диаграмма слишком сильно увеличена, значения начинают дублироваться, как показано здесь:

Screenshot 2019-07-19 at 17 59 11

В этом случае функция granularity не работает, так как работает с разницей между числами.

У вас есть идея, как я могу предотвратить повторение этих ярлыков?

Спасибо

Установить granularityEnabled на ложную работу для меня
leftAxis.granularityEnabled = true

Привет, ребята, я хочу, чтобы значение xAxis не повторялось при увеличении
мой формирователь:
func stringForValue (_ значение: Double, ось: AxisBase?) -> String {
пусть дата = Дата (timeIntervalSince1970: значение)
дата возврата.formattedString(withDateFormat: .daymonth)
}
также я использую гранулярность, но у меня все еще та же проблема
xAxis.granularity = 1,0
xAxis.granularityEnabled = истина

может кто знает как решить плз?

@Ааймек
у меня такая же проблема, вы нашли решение?

У меня такая же проблема, когда я принудительно подсчитываю метки по оси X и рисую несколько точек.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

newbiebie picture newbiebie  ·  3Комментарии

guoyutaog picture guoyutaog  ·  3Комментарии

valeIT picture valeIT  ·  3Комментарии

Shunshine07 picture Shunshine07  ·  3Комментарии

Bharati555 picture Bharati555  ·  4Комментарии