Charts: Detener la duplicación de etiquetas de eje.

Creado en 24 ago. 2015  ·  51Comentarios  ·  Fuente: danielgindi/Charts

Dentro de la aplicación, tengo un problema en el que se repiten las etiquetas en el eje izquierdo de BarChartView o LineChartView .

Primero agregué el fragmento a continuación para garantizar que la cantidad de etiquetas en el eje no exceda el valor máximo en los datos y.

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

Esto aseguró que si el valor máximo en los datos y era 3 entonces solo habría etiquetas 3 dentro del eje. Ahora bien, esto funcionaba bien si el gráfico no era interactivo, es decir, el usuario no podía hacer zoom en el gráfico.

Tan pronto como el usuario hace zoom, obviamente, el recuento de las etiquetas sigue siendo el mismo y el formateador de valores llena los espacios en blanco, lo que permite que se repita un valor.

_Ejemplo de eje sin valores duplicados_
screen shot 2015-08-24 at 5 07 29 pm

_Ejemplo del mismo gráfico pero ampliado_
screen shot 2015-08-24 at 5 07 54 pm

Las capturas de pantalla muestran el eje izquierdo repitiendo el valor 2 . ¿Cuál es su mejor sugerencia para resolver este problema de etiquetas repetitivas? Cualquier ayuda será de gran utilidad. Si necesitas más información házmelo saber.

Gracias

Comentario más útil

Esto se lanzó en 2.2.4, como la función granularity

Todos 51 comentarios

Supongo que no es la etiqueta duplicada, pero contiene valores decimales y un formateador de enteros. Debe verificar cuál es el valor sin procesar para cada etiqueta del eje x y cómo le da formato cuando dibuja las etiquetas del eje x en el renderizador del eje y.

Pude hacer esto agregando una verificación para garantizar que el intervalo de cada etiqueta sea siempre un valor completo.
El cambio está dentro de la función computeAxisValues() de la clase ChartYAxisRenderer

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

Si el formateador de valores solicita que no haya dígitos fraccionarios, entonces reduce los intervalos y si es menor que el número entero 1 establece el intervalo en 1 .

¿Le gustaría una solicitud de extracción?

Gracias por tu ayuda.

Si tiene valores decimales, ¿por qué maxFractionDigits es 0? Creo que es el problema del formateador.

No quiero valores decimales, por eso configuro maximumFractionDigits = 0

amigo, sus datos son decimales, y solo quiere usar el formateador para abandonar los dígitos de fracción, no tiene sentido. ¿Por qué no convertir sus datos a números enteros primero?

Los valores y que le doy al gráfico son

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

Una vez que creo un ChartDataSet estos valores se duplican.

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

Esto se debe a que su clase ChartDataEntry tiene el valor de Double

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

Aunque los valores se han cambiado a un doble, los gráficos muestran el incremento correcto de las etiquetas al principio, pero tan pronto como se amplía el gráfico, el ChartYAxisRenderer desea llenar los espacios y, como mi formateador de valores eliminó cualquier dígitos fraccionarios que muestra como un valor duplicado.

No quiero que el gráfico asuma que quiero valores adicionales entre los números enteros, ya que solo quiero mostrar una etiqueta para un número entero.

Esto me lleva a ver que estoy proporcionando los datos correctos al gráfico, pero el gráfico hace suposiciones sobre lo que quiero hacer. Esto está bien para un valor predeterminado, pero también debería proporcionar la opción de mostrar solo números enteros en el eje.

Al agregar el control contra el formateador de valores, permite este comportamiento. Es posible que conozca una mejor manera de proporcionar este comportamiento en lugar de verificar el formateador de valores, pero es un caso de uso que algunas personas quieren.

Acabo de darme cuenta de que estoy usando el código base en la confirmación a7e30dd16fbfaecb8e44c01ad8618a3a745fd101 y cuando este cambio se implementa en la última confirmación de Charts, no actúa como se esperaba.

¿Sería capaz de aconsejarme sobre la mejor manera de lograr el comportamiento que quiero?

Adjunto un gif del comportamiento esperado.

A continuación, puede ver que ninguna etiqueta muestra el mismo valor y el gráfico no intenta colocar ninguna etiqueta entre otras etiquetas, ya que existe el requisito de que las etiquetas sean valores completos.

chart

Ah, ya veo. Si hace zoom, digamos [3,4], el rango sería [3,4] y el eje quiere mostrar [3.0, 3.2, 3.4, 3.6, 3.8, 4.0], y no quiere dígitos fraccionarios, ¿Lo es?

En realidad, no hay nada que pueda hacer... ya que sus datos son bastante pequeños y tenemos que mostrar de 4 a 6 etiquetas allí... ¿Qué sucede si el rango es [0,1] y necesita mostrar 5 etiquetas? muestra otros dígitos además de fraccionarios?

Creo que está bien mostrar dígitos fraccionarios si el rango es demasiado pequeño, pero si realmente no lo quieres, puedes hacerlo como lo hiciste. O aceptaría mostrar solo la etiqueta máxima y mínima llamada showOnlyMinMaxEnabled

Por cierto, tus capturas de pantalla funcionan muy bien, resolvieron tu problema

También hay algunas propiedades para ayudarlo a limitar el número de etiquetas. Puede intentar modificar y ajustar para diferentes niveles de escala.

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

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

        forceLabelsEnabled = force
    }

Para tener el mismo comportamiento en el eje Y es necesario establecer un límite de zoom Y. #382

388

@steprescott , ¿el #388 resolvió tu problema?

Al mirar el compromiso para el problema n. ° 388, el único cambio es una nueva propiedad en la ventana gráfica.

¿Cómo obtendría el comportamiento previsto que se muestra en el gif pero con sus cambios?

Hola @steprescott , prueba con [_chartView.viewPortHandler setMaximumScaleY: 2.f]; por ejemplo, así la granularidad del zoom no es tan grande como para mostrar valores repetidos. Un buen ejemplo es cuando tiene una línea char horizontal sin límite, todos los valores Y se repiten cuando el zoom es grande. Con MaximumScaleY esta repetición no ocurre.

Sin limite:
screen shot 2015-09-22 at 23 29 16

Con límite 2f:
screen shot 2015-09-22 at 23 30 07

Hola @noais

Eso funciona en un conjunto de datos que tiene un rango de valores mayor, pero si tiene un rango de valores pequeño, por ejemplo, una matriz de valores de 0 a 7, acercar por un factor de 2 podría proporcionar etiquetas duplicadas.

Aunque al limitar el factor de zoom ha resuelto su problema, no resuelve el problema de repetir valores completos.

Obtuve los resultados esperados al editar la clase ChartYAxisRenderer apuntando a la confirmación a7e30dd16fbfaecb8e44c01ad8618a3a745fd101.

Esto se hizo pisoteando el valor.

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

Aunque esto funcionó (pero no cuando se usa HEAD de este repositorio), creo que ustedes conocerán un lugar mejor dentro de su marco para colocar esto y proporcionar el mismo resultado que se muestra en el gif.

Tal vez una propiedad allowRepeatingValues BOOL en un eje. Ustedes sabrán mejor.

Sí, tienes razón, esta fue una solución. Déjame intentar ver si es fácil crear algún método como allowRepeatingValues.

Eso sería de gran ayuda, gracias.

Hola @noais y @liuxuan30. ¿Has tenido oportunidad de investigar esto? Pude obtener el efecto requerido usando el marco, pero no sé dónde debería ubicarse mejor esta propiedad dentro del marco y si hay una mejor manera de lograr el mismo resultado.

Gracias por tu tiempo.

Sigo pensando que es porque el formateador que produjo etiquetas duplicadas con dígitos pequeños, no el algoritmo. Si elimina el formateador, mostrará el número correctamente, ¿verdad?
Puede resolverlo con su código, pero no estoy seguro de si es bueno para todos.
@danielgindi que opinas

Hola chicos, votando por allowRepeatingValues, tengo números pequeños y no quiero mostrar el valor del eje y duplicado

Cuando todos mis valores son cero, obtengo estas etiquetas de eje repetitivas:
chart

Además, me di cuenta de que, aunque el fragmento de código que tengo hace lo que necesito, no elimina valores duplicados, simplemente permite números enteros. Entonces, verificar con el formateador de números no es una forma horrible de agregar esto.

Lo que ese fragmento no permite es la eliminación de valores duplicados, por lo que si los valores fueran 1.1, 1.2, 1.2, 1.3 y deseara mantener el dígito decimal único, no funcionaría. Ustedes sabrán el mejor lugar y la mejor implementación para esta función y para que las personas dediquen tiempo a analizar los problemas actuales del marco y luego voten a favor, muestra que es una opción que otros también quieren.

permitir valores repetidos :+1:

@noais @liuxuan30 ¿Tiene una solución mejor para esto que la que he sugerido?

no, excepto por allowRepeatingValues.. Porque su problema original es sobre los formateadores. no quiere dígitos decimales en un nivel, pero sus datos en realidad tienen el siguiente nivel

¡Idealmente, el gráfico no debería mostrar valores repetidos, nunca! ¿Se pueden ocultar los valores repetidos con alguna lógica, dando como resultado solo valores únicos?

@vigyanhoon no se trata de 'repetir' valores detrás, es el formateador el que hace que el valor se 'repita'. Si no desea repetir, proporcione un formateador decimal que pueda resolverlo.

@ liuxuan30 ¿Puede explicar qué quiere decir con "_dar un formateador decimal_"? Con mis datos le di un formateador que configuró el maximumFractionDigits = 0 . No estoy seguro de cómo obtener los resultados esperados con lo que hay actualmente. ¿Ha podido producir un gráfico con el marco tal cual da los mismos resultados que mi gif que publiqué el 28 de agosto?

¿Querías usar numberFormatter.allowsFloats = NO, si es así, no me ayudó, todavía veo INT duplicados? La única forma en que logré NO mostrar valores repetitivos es usar 2 etiquetas en xAxis (arriba/abajo)

@steprescott lo siento si no estoy claro. MaximumFractionDigits no debe ser 0, de lo contrario, solo mostrará la parte entera. Encontré problemas similares, si el rango de datos es pequeño y se necesitan de 5 a 6 etiquetas, dar el máximo de FracciónDigits = 0 tendrá valores repetidos. Supongo que no hay una manera fácil de arreglar esto. piense si el rango de datos es [0,2] y tengo que mostrar 5 etiquetas: 0, 0.4, 0.8, 1.2, 1.6, 2.0. Si aplicamos maximumFractionDigits = 0, puede ser 0, 0, 1, 1, 2, 2

@injectios , ¿qué tal MaximumFractionDigits = 2 o incluso 4?

¡Hola a todos!
Estoy teniendo este mismo problema.

@ liuxuan30 según el tipo de datos, no tiene sentido tener decimales. Como un gráfico de humanos, nunca tendrás 1.5 humanos, es 1 o 2.

@jpros tienes un punto, pero desde el punto de vista matemático, no podemos tener 4 etiquetas sin decimales en el rango [0,2].

Por lo tanto, active yAxis.showOnlyMinMaxEnabled para evitar valores repetidos como solución por ahora,
O implementa su lógica para calcular sus propios valores en ChartYAxisRenderer.computeAxis para evitar,
O tenemos que esperar a la función 'allowRepeatValues'

@PhilJay , ¿tenemos alguna solución para eso actualmente? :-)

Desde un punto de vista de Android (y ofc iOS), esta línea aquí: https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java#L108

Podría ser un lugar para abordar este problema. Tiene el float interval de las etiquetas de eje calculado, y podría usarlo para evitar más cambios en las etiquetas si dos etiquetas tuvieran el mismo formato.
Eso es justo lo que me viene a la mente cuando pienso rápidamente en ello. ¿Qué piensas?

Me deshice de la duplicación estableciendo un valor máximo

ejeizquierdo.customAxisMax = maxYLabelCount

@vigyanhoon es algo totalmente diferente, los valores pueden ser millones, mientras que maxYLabelCount no puede. customAxisMax es definir el valor máximo que podría tener el rango del eje.

+1 para resolver el problema de renderizado. También tengo un gráfico de personas, y tengo [0, 0, 1, 1, 2, 2]. Establecer numberFormatter.maximumFractionDigits en cualquier otra cosa que no sea 0 no tiene ningún sentido.

El siguiente código sugerido por @steprescott también me lo solucionó. Lo agregué en mi tenedor aquí:

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

¿Un PR podría cerrar este problema? ¿Qué opinas @danielgindi @liuxuan30 @steprescott ? ¿Hay casos que este código no soluciona? Si es así, ¿cuáles son mejores soluciones?

@natanrolnik, ¿qué pasa si el usuario hace zoom y el rango se convierte en [25.2, 25.3]? El intervalo sería 1,0 cuando debería ser, digamos 0,02.
Debería ayudar si el usuario establece específicamente el número máximo de fracción en 0, limitamos el intervalo. Sin embargo, no probé valores negativos.
Todavía no tenemos una solución mejor, pero supongo que una característica como 'allowRepeatValues' es lo que se nos ocurre.

¡Estoy de acuerdo con respecto a allowRepeatedValues !

Creo que el @steprescott es una buena solución. Solo necesita ajustar el valor uno a una variable de granularidad.

Con este problema de @liuxuan30 ya no existe.

Si ponemos este código en la línea 75 de ChartYAxisRenderer:

interval = interval < granuality ? granuality : interval       

https://github.com/noais/ios-charts/compare/master...Noais
¿Qué piensas?

Ok, ahora está cerrado pero no está fusionado con el maestro. ¿Cuándo sería probable que sucediera esto?

Esto se lanzó en 2.2.4, como la función granularity

No estoy seguro de si debería publicar este problema aquí, pero tiene sentido para mí.

Tengo un problema muy similar con mis etiquetas xAxis. Tengo un IAxisValueFormatter personalizado que devuelve cadenas de tiempo, da horas como esta "22:00", "23:00" para algunos gráficos, días de la semana como este "lunes", "jueves". para otros etc..

Cuando el gráfico se amplía demasiado, los valores comienzan a duplicarse como se muestra aquí:

Screenshot 2019-07-19 at 17 59 11

En este caso la función granularity no funciona ya que funciona con la diferencia entre números.

¿Tienes alguna idea de cómo podría evitar que esas etiquetas se repitan?

Gracias

Establecer granularityEnabled para falso trabajo para mí
leftAxis.granularityEnabled = true

Hola chicos, quiero que el valor de xAxis no se repita cuando se acerca el zoom
mi formador:
func stringForValue(_ valor: Doble, eje: AxisBase?) -> Cadena {
let fecha = Fecha (intervalo de tiempo desde 1970: valor)
fecha de retorno.formattedString(withDateFormat: .daymonth)
}
también uso granularidad, pero sigo teniendo el mismo problema
xAxis.granularity = 1.0
xAxis.granularityEnabled = verdadero

¿alguien sabe como solucionarlo plz?

@Aaimek
tengo el mismo problema, encontraste la solucion?

Tengo el mismo problema cuando fuerzo el recuento de etiquetas del eje x y trazo algunos puntos.

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

kirti0525 picture kirti0525  ·  3Comentarios

BrandonShega picture BrandonShega  ·  4Comentarios

kwstasna picture kwstasna  ·  3Comentarios

Shunshine07 picture Shunshine07  ·  3Comentarios

brytnvmg picture brytnvmg  ·  4Comentarios