Charts: Arrêtez la duplication des étiquettes d'axe.

Créé le 24 août 2015  ·  51Commentaires  ·  Source: danielgindi/Charts

Dans l'application, j'ai un problème où les étiquettes sur l'axe gauche d'un BarChartView ou d'un LineChartView se répètent.

J'ai d'abord ajouté l'extrait ci-dessous pour m'assurer que le nombre d'étiquettes sur l'axe ne dépasse pas la valeur maximale dans les données y.

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

Cela garantissait que si la valeur maximale dans les données y était 3 , il n'y aurait que 3 étiquettes dans l'axe. Maintenant, cela fonctionnait bien si le graphique n'était pas interactif, c'est-à-dire que l'utilisateur ne pouvait pas zoomer sur le graphique.

Dès que l'utilisateur zoome, le nombre d'étiquettes reste évidemment le même et le formateur de valeur comble les lacunes permettant à une valeur de se répéter.

_Exemple d'axe sans valeurs en double_
screen shot 2015-08-24 at 5 07 29 pm

_Exemple du même graphique mais agrandi_
screen shot 2015-08-24 at 5 07 54 pm

Les captures d'écran montrent l'axe de gauche répétant la valeur 2 . Quelle est votre meilleure suggestion pour résoudre ce problème d'étiquette récurrent ? Toute aide serait reconnaissante. Si vous avez besoin de plus amples informations, faites-le moi savoir.

Merci

Commentaire le plus utile

Ceci est publié en 2.2.4, en tant que fonctionnalité granularity

Tous les 51 commentaires

Je suppose que ce n'est pas l'étiquette dupliquée, mais elle contient des valeurs décimales et un formateur d'entiers ? Vous devez vérifier quelle est la valeur brute de chaque étiquette d'axe x et comment vous la formatez lorsqu'elle dessine les étiquettes xAxis dans le rendu d'axe y.

J'ai pu le faire en ajoutant une vérification pour m'assurer que l'intervalle de chaque étiquette est toujours une valeur entière.
Le changement est dans la fonction computeAxisValues() de la classe ChartYAxisRenderer

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

Si le formateur de valeur demande qu'il n'y ait pas de chiffres fractionnaires, il fixe les intervalles et s'il est inférieur au nombre entier 1 , il définit l'intervalle sur 1 .

Souhaitez-vous une demande de tirage ?

Merci de votre aide.

Si vous avez des valeurs décimales, pourquoi maximumFractionDigits vaut 0 ? Je pense que c'est le problème du formateur.

Je ne veux pas de valeurs décimales, c'est pourquoi j'ai défini maximumFractionDigits = 0

pal, vos données sont décimales, et vous voulez juste utiliser le formateur pour abandonner les chiffres des fractions, cela n'a pas de sens. Pourquoi ne pas d'abord convertir vos données en nombres entiers ?

Les valeurs y que je donne au graphique sont

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

Une fois que je crée un ChartDataSet ces valeurs sont alors doublées.

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

C'est parce que votre classe ChartDataEntry contient la valeur en tant que Double

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

Bien que les valeurs aient été modifiées en double, les graphiques affichent d'abord l'incrément correct des étiquettes, mais dès que le graphique est agrandi, le ChartYAxisRenderer souhaite combler les lacunes et comme mon formateur de valeur a supprimé tout chiffres fractionnaires qu'il affiche comme une valeur dupliquée.

Je ne veux pas que le graphique suppose que je veux des valeurs supplémentaires entre les nombres entiers, car je veux seulement afficher une étiquette pour un nombre entier.

Cela m'amène donc à voir que je fournis les données correctes au graphique, mais le graphique fait des hypothèses sur ce que je veux faire. C'est bien pour une valeur par défaut, mais devrait également fournir l'option de n'afficher que des nombres entiers sur l'axe.

En ajoutant la vérification par rapport au formateur de valeur, cela permet ce comportement. Vous connaissez peut-être une meilleure façon de fournir ce comportement plutôt que de vérifier le formateur de valeur, mais c'est un cas d'utilisation que certaines personnes souhaitent.

Je viens de remarquer que j'utilise la base de code au commit a7e30dd16fbfaecb8e44c01ad8618a3a745fd101 et lorsque ce changement est implémenté dans le dernier commit de Charts, il n'agit pas comme prévu.

Seriez-vous en mesure de me conseiller sur la meilleure façon d'obtenir le comportement que je souhaite ?

J'ai joint un gif du comportement attendu.

Ci-dessous, vous pouvez voir qu'aucune étiquette n'affiche la même valeur et que le graphique n'essaie pas de placer une étiquette entre d'autres étiquettes car il est nécessaire que les étiquettes soient des valeurs entières.

chart

Ah, je vois. Si vous zoomez sur disons [3,4], la plage serait [3,4] et l'axe veut afficher [3.0, 3.2, 3.4, 3.6, 3.8, 4.0], et vous ne voulez pas de chiffres fractionnaires, est-ce?

En fait, je ne peux rien faire... puisque vos données sont assez petites et que nous devons y afficher 4 à 6 étiquettes... Et si la plage est [0,1] et que vous devez afficher 5 étiquettes, qu'est-ce qui peut vous affichez autre que des chiffres fractionnaires ?

Je pense que c'est bien d'afficher des chiffres fractionnaires si la plage est trop petite, mais si vous ne le voulez vraiment pas, vous pouvez le faire comme vous l'avez fait. Ou vous accepteriez de n'afficher que l'étiquette max et min appelée showOnlyMinMaxEnabled

BTW, vos captures d'écran fonctionnent très bien, ont résolu votre problème

Il existe également des propriétés pour vous aider à limiter le nombre d'étiquettes. Vous pouvez essayer de modifier et d'adapter à différents niveaux d'échelle.

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

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

        forceLabelsEnabled = force
    }

Pour avoir le même comportement sur l'axe Y, il est nécessaire de définir une limite de zoom Y. #382

388

@steprescott , le #388 a-t-il résolu votre problème ?

En regardant le commit pour le problème #388, le seul changement est une nouvelle propriété sur la fenêtre.

Comment puis-je obtenir le comportement prévu qui est affiché dans le gif mais avec vos modifications ?

Salut @steprescott , essayez avec [_chartView.viewPortHandler setMaximumScaleY: 2.f] ; par exemple, comme ceci, la granularité du zoom n'est pas si grande pour afficher des valeurs répétées. Un bon exemple est lorsque vous avez une ligne de caractères horizontale sans limite, toutes les valeurs Y sont répétées lorsque le zoom est grand. Avec MaximumScaleY cette répétition ne se produit pas.

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

Avec limite 2f :
screen shot 2015-09-22 at 23 30 07

Salut @noais

Cela fonctionne sur un ensemble de données qui a une plage de valeurs plus large, mais si vous avez une petite plage de valeurs, par exemple un tableau de valeurs de 0 à 7, un zoom avant d'un facteur 2 pourrait potentiellement fournir des étiquettes en double.

Bien que la limitation du facteur de zoom ait résolu votre problème, cela ne résout pas le problème de la répétition de valeurs entières.

J'ai obtenu les résultats attendus lors de la modification de la classe ChartYAxisRenderer pointant vers le commit a7e30dd16fbfaecb8e44c01ad8618a3a745fd101.

Cela a été fait en plaquant la valeur.

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

Bien que cela ait fonctionné (mais pas lors de l'utilisation de HEAD de ce référentiel), je pense que vous connaîtrez un meilleur endroit dans votre cadre pour le placer afin de fournir le même résultat que celui indiqué dans le gif.

Peut-être une propriété allowRepeatingValues BOOL sur un axe. Vous saurez mieux.

Oui, vous avez raison, c'était un travail autour. Laissez-moi essayer de voir s'il est facile de créer une méthode comme allowRepeatingValues.

Ce serait très utile, merci.

Salut @noais et @liuxuan30. Avez-vous eu l'occasion d'enquêter là-dessus ? J'ai pu obtenir l'effet requis en utilisant le cadre, mais je ne sais pas où cette propriété devrait se situer au mieux dans le cadre et s'il existe un meilleur moyen d'obtenir le même résultat.

Merci pour votre temps.

Je pense toujours que c'est parce que le formateur a produit des étiquettes dupliquées avec de petits chiffres, pas l'algorithme. Si vous supprimez le formateur, il affichera le numéro correctement, n'est-ce pas ?
Vous pouvez le résoudre avec votre code, mais je ne suis pas sûr que ce soit un bon pour tout le monde.
@danielgindi qu'en pensez-vous

Salut les gars, je vote pour allowRepeatingValues, j'ai de petits nombres et je ne veux pas afficher la valeur de l'axe y en double

Lorsque toutes mes valeurs sont nulles, j'obtiens ces étiquettes d'axe répétitives-
chart

De plus, j'ai remarqué que bien que l'extrait de code que j'ai fasse ce dont j'ai besoin, il ne supprime pas les valeurs en double, n'autorisant que les nombres entiers. Donc, en vérifiant le formateur de nombres, ce n'est pas une façon horrible d'ajouter cela.

Ce que cet extrait ne permet pas, c'est de supprimer les valeurs en double, donc si les valeurs étaient 1.1, 1.2, 1.2, 1.3 et que vous souhaitiez conserver le chiffre décimal unique, cela ne fonctionnerait pas. Vous saurez le meilleur endroit et la meilleure implémentation pour cette fonctionnalité et pour que les gens passent du temps à examiner les problèmes actuels du cadre et pour qu'ils votent ensuite, cela montre que c'est une option que d'autres veulent aussi.

allowRepeatingValues :+1 :

@noais @liuxuan30 Avez-vous une meilleure solution à cela que ce que j'ai suggéré ?

non, sauf pour allowRepeatingValues.. Parce que votre problème d'origine concerne les formateurs. vous ne voulez pas de chiffres décimaux à un niveau mais vos données ont en fait le niveau suivant

Idéalement, le graphique ne devrait jamais afficher de valeurs répétitives ! Les valeurs répétitives peuvent-elles être masquées avec une certaine logique, aboutissant ainsi à des valeurs uniques ?

@vigyanhoon ce ne sont pas des valeurs "répétitives" derrière, c'est le formateur qui provoque la "répétition" de la valeur. Si vous ne voulez pas répéter, donnez un formateur décimal peut le résoudre.

@liuxuan30 Pouvez-vous expliquer ce que vous entendez par "_donner un formateur décimal_" ? Avec mes données, j'ai donné un formateur qui a défini le maximumFractionDigits = 0 . Je ne sais pas comment obtenir les résultats escomptés avec ce qui existe actuellement ? Avez-vous pu produire un graphique avec le cadre tel quel qui donne les mêmes résultats que mon gif que j'ai posté le 28 août ?

Vouliez-vous utiliser numberFormatter.allowsFloats = NO, si oui, cela ne m'a pas aidé, je vois toujours des INT en double ? ! La seule façon dont j'ai réussi à NE PAS afficher les valeurs répétitives est d'utiliser 2 étiquettes sur xAxis (haut/bas)

@steprescott désolé si je ne suis pas clair. MaximumFractionDigits ne doit pas être 0, sinon il n'affichera que la partie entière. J'ai rencontré des problèmes similaires, si la plage de données est petite et que 5 à 6 étiquettes sont nécessaires, donner maximumFractionDigits = 0 aura des valeurs répétées. Il n'y a pas de moyen facile de résoudre ce problème, je suppose. réfléchissez si la plage de données est [0,2], et je dois afficher 5 étiquettes : 0, 0,4, 0,8, 1,2, 1,6, 2,0. Si nous appliquons maximumFractionDigits = 0, c'est peut-être 0, 0, 1, 1, 2, 2

@injectios , que diriez-vous de MaximumFractionDigits = 2 ou même 4 ?

Salut tout le monde!
J'ai le même problème.

@ liuxuan30 selon le type de données, cela n'a pas de sens d'avoir des décimales. Comme un tableau des humains, vous n'aurez jamais 1,5 humain, c'est 1 ou 2.

@jpros vous avez un point, mais à partir du point mathématique, nous ne pouvons pas avoir 4 étiquettes sans décimales dans la plage [0,2].

Donc, activez yAxis.showOnlyMinMaxEnabled pour éviter les valeurs répétées comme solution de contournement pour l'instant,
Soit vous implémentez votre logique pour calculer vos propres valeurs en ChartYAxisRenderer.computeAxis à éviter,
Ou nous devons attendre la fonctionnalité 'allowRepeatValues'

@PhilJay avons-nous une solution pour cela actuellement ? :-)

Depuis un POV Android (et ofc iOS), cette ligne ici : https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java#L108

Pourrait être un endroit pour résoudre ce problème. Le float interval des étiquettes d'axe est calculé et pourrait l'utiliser pour empêcher d'autres modifications des étiquettes si deux étiquettes étaient formatées de la même manière.
C'est exactement ce qui me vient à l'esprit quand j'y pense rapidement. Qu'est-ce que tu penses?

Je me suis débarrassé de la duplication en définissant une valeur maximale

leftAxis.customAxisMax = maxYLabelCount

@vigyanhoon c'est une chose totalement différente, les valeurs peuvent être des millions, alors que maxYLabelCount ne le peut pas. customAxisMax consiste à définir la valeur maximale de la plage d'axes.

+1 pour résoudre le problème de rendu. J'ai aussi un graphique de personnes, et j'ai [0, 0, 1, 1, 2, 2]. Définir le numberFormatter.maximumFractionDigits sur autre chose que 0 n'a aucun sens.

Le code suivant suggéré par @steprescott a également été corrigé pour moi. Je l'ai ajouté dans mon fork ici:

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

Est-ce qu'un RP pourrait clore ce problème ? Qu'en pensez-vous @danielgindi @liuxuan30 @steprescott ? Y a-t-il des cas où ce code ne résout pas? Si oui, quelles sont les meilleures solutions ?

@natanrolnik et si le zoom avant et la plage de l'utilisateur deviennent [25.2, 25.3] ? L'intervalle serait de 1,0 alors qu'il devrait l'être, disons 0,02.
Cela devrait aider si l'utilisateur définit spécifiquement le nombre de fractions maximum sur 0, nous limitons l'intervalle. Je n'ai pas testé les valeurs négatives.
Nous n'avons pas encore de meilleure solution, mais je suppose qu'une fonctionnalité telle que "allowRepeatValues" est ce à quoi nous pouvons penser ?

Je suis d'accord pour allowRepeatedValues !

Je pense que le @steprescott est une bonne solution. Il suffit d'ajuster la valeur un à une variable de granularité.

Avec ce problème @ liuxuan30 n'existe plus.

Si nous mettons ce code à la ligne 75 dans ChartYAxisRenderer :

interval = interval < granuality ? granuality : interval       

https://github.com/noais/ios-charts/compare/master...Noais
Qu'est-ce que tu penses?

Ok, donc c'est maintenant fermé mais il n'est pas fusionné dans master. Quand est-ce que cela risquerait de se produire ?

Ceci est publié en 2.2.4, en tant que fonctionnalité granularity

Je ne sais pas si je devrais poster ce problème ici, mais cela me semble logique.

J'ai un problème très similaire avec mes étiquettes xAxis. J'ai un IAxisValueFormatter personnalisé qui renvoie des chaînes pour l'heure, il donne des heures comme celle-ci "22h00", "23h00" pour certains graphiques, des jours de semaine comme ceci "Lun.", "Jeu". pour les autres etc..

Lorsque le graphique est trop agrandi, les valeurs commencent à se dupliquer, comme illustré ici :

Screenshot 2019-07-19 at 17 59 11

Dans ce cas, la fonctionnalité granularity ne fonctionne pas car elle fonctionne avec la différence entre les nombres.

Avez-vous une idée de la façon dont je pourrais empêcher ces étiquettes de se répéter ?

Merci

Définir la granularitéEnabled sur un faux travail pour moi
leftAxis.granularityEnabled = true

Bonjour les gars, je veux que la valeur xAxis ne se répète pas lors d'un zoom avant
mon Formateur :
func stringForValue(_ valeur : Double, axe : AxisBase ?) -> Chaîne {
let date = Date(timeIntervalSince1970 : valeur)
return date.formattedString(withDateFormat: .daymonth)
}
j'utilise aussi la granularité, mais j'ai toujours le même problème
xAxis.granularity = 1.0
xAxis.granularityEnabled = vrai

quelqu'un peut-il savoir comment le résoudre plz?

@Aaimek
J'ai le même problème, avez-vous trouvé la solution ?

J'ai le même problème lorsque je force le nombre d'étiquettes sur l'axe des x et que je trace quelques points.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

ahmedsafadii picture ahmedsafadii  ·  3Commentaires

deepumukundan picture deepumukundan  ·  3Commentaires

kwstasna picture kwstasna  ·  3Commentaires

PrashantKT picture PrashantKT  ·  3Commentaires

newbiebie picture newbiebie  ·  3Commentaires