Charts: Beenden Sie das Duplizieren von Achsenbeschriftungen.

Erstellt am 24. Aug. 2015  ·  51Kommentare  ·  Quelle: danielgindi/Charts

Innerhalb der App habe ich ein Problem, bei dem sich die Beschriftungen auf der linken Achse von entweder BarChartView oder LineChartView wiederholen.

Ich habe zuerst den folgenden Ausschnitt hinzugefügt, um sicherzustellen, dass die Anzahl der Beschriftungen auf der Achse den Maximalwert in den y-Daten nicht überschreitet.

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

Dadurch wurde sichergestellt, dass bei einem Höchstwert in den y-Daten von 3 nur 3 Beschriftungen innerhalb der Achse vorhanden wären. Dies funktionierte nun gut, wenn der Graph nicht interaktiv war, dh der Benutzer konnte das Diagramm nicht zoomen.

Sobald der Benutzer zoomt, bleibt die Anzahl der Beschriftungen natürlich gleich und der Werteformatierer füllt die Lücken, sodass sich ein Wert wiederholen kann.

_Beispiel einer Achse ohne doppelte Werte_
screen shot 2015-08-24 at 5 07 29 pm

_Beispiel für dasselbe Diagramm, aber vergrößert_
screen shot 2015-08-24 at 5 07 54 pm

Die Screenshots zeigen die linke Achse, die den Wert 2 wiederholt. Was ist Ihr bester Vorschlag zur Lösung dieses Problems mit sich wiederholenden Etiketten? Jede Hilfe wäre dankbar. Wenn Sie weitere Informationen benötigen, lassen Sie es mich wissen.

Danke

Hilfreichster Kommentar

Dies wird in 2.2.4 als Funktion granularity veröffentlicht

Alle 51 Kommentare

Ich denke, es ist nicht das Label dupliziert, aber es enthält Dezimalwerte und einen Integer-Formatierer? Sie müssen überprüfen, was der Rohwert für jede x-Achsenbeschriftung ist und wie Sie ihn formatieren, wenn er die x-Achsenbeschriftungen im y-Achsen-Renderer zeichnet.

Ich konnte dies tun, indem ich eine Überprüfung hinzufügte, um sicherzustellen, dass das Intervall jeder Bezeichnung immer ein ganzzahliger Wert ist.
Die Änderung erfolgt innerhalb der Funktion computeAxisValues() der Klasse ChartYAxisRenderer

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

Wenn der Wertformatierer verlangt, dass keine Nachkommastellen vorhanden sind, werden die Intervalle unterschritten, und wenn er kleiner als die ganze Zahl 1 ist, setzt er das Intervall auf 1 .

Möchten Sie einen Pull-Request?

Danke für Ihre Hilfe.

Wenn Sie Dezimalwerte haben, warum ist maximumFractionDigits 0? Ich denke, es ist das Formatierungsproblem.

Ich möchte keine Dezimalwerte, deshalb setze ich maximumFractionDigits = 0

Kumpel, Ihre Daten sind dezimal, und Sie möchten nur den Formatierer verwenden, um die Bruchziffern aufzugeben, es macht keinen Sinn. Warum konvertieren Sie Ihre Daten nicht zuerst in Ganzzahlen?

Die y-Werte, die ich dem Diagramm gebe, sind

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

Sobald ich ein ChartDataSet erstellt habe, sind diese Werte dann doppelt.

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

Dies liegt daran, dass Ihre Klasse ChartDataEntry den Wert als Double enthält

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

Obwohl die Werte auf das Doppelte geändert wurden, zeigen die Diagramme zunächst die korrekte Schrittweite der Beschriftungen, aber sobald das Diagramm vergrößert wird, möchte das ChartYAxisRenderer die Lücken füllen, und da mein Wertformatierer alle entfernt hat Nachkommastellen werden als doppelter Wert angezeigt.

Ich möchte nicht, dass das Diagramm davon ausgeht, dass ich zusätzliche Werte zwischen den ganzen Zahlen haben möchte, da nur eine Beschriftung für eine ganze Zahl angezeigt werden soll.

Das führt mich also zu der Erkenntnis, dass ich dem Diagramm die richtigen Daten liefere, das Diagramm jedoch Annahmen darüber trifft, was ich tun möchte. Dies ist für einen Standard in Ordnung, sollte aber die Option bieten, auch nur ganze Zahlen auf der Achse anzuzeigen.

Durch Hinzufügen der Prüfung gegen den Wertformatierer wird dieses Verhalten ermöglicht. Sie kennen vielleicht einen besseren Weg, um dieses Verhalten bereitzustellen, anstatt den Wertformatierer zu überprüfen, aber es ist ein Anwendungsfall, den einige Leute wollen.

Ich habe gerade festgestellt, dass ich die Codebasis beim Commit a7e30dd16fbfaecb8e44c01ad8618a3a745fd101 verwende und wenn diese Änderung in den neuesten Commit von Charts implementiert wird, funktioniert sie nicht wie erwartet.

Können Sie mir Tipps geben, wie ich das gewünschte Verhalten am besten erreichen kann?

Ich habe ein gif des erwarteten Verhaltens angehängt.

Unten sehen Sie, dass keine Beschriftungen denselben Wert aufweisen und das Diagramm nicht versucht, Beschriftungen zwischen anderen Beschriftungen zu platzieren, da die Beschriftungen ganze Werte sein müssen.

chart

Ah ich sehe. Wenn Sie beispielsweise auf [3,4] zoomen, wäre der Bereich [3,4] und die Achse möchte [3,0, 3,2, 3,4, 3,6, 3,8, 4,0] anzeigen, und Sie möchten keine Nachkommastellen, ist es?

Es ist eigentlich nichts, was ich tun kann ... da Ihre Daten ziemlich klein sind und wir dort 4-6 Labels anzeigen müssen ... Was ist, wenn der Bereich [0,1] ist und Sie 5 Labels anzeigen müssen, was kann Sie zeigen andere als Nachkommastellen an?

Ich denke, es ist in Ordnung, Nachkommastellen anzuzeigen, wenn der Bereich zu klein ist, aber wenn Sie es wirklich nicht wollen, können Sie es so machen, wie Sie es getan haben. Oder Sie würden akzeptieren, dass nur das Max- und Min-Label namens showOnlyMinMaxEnabled wird

Übrigens, deine Screenshots funktionieren großartig, dein Problem wurde gelöst

Es gibt auch einige Eigenschaften, mit denen Sie die Anzahl der Labels begrenzen können. Sie können versuchen, verschiedene Maßstabsebenen zu ändern und anzupassen.

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

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

        forceLabelsEnabled = force
    }

Um das gleiche Verhalten auf der Y-Achse zu haben, muss eine Y-Zoomgrenze eingestellt werden. #382

388

@steprescott , ist #388 dein Problem gelöst?

Wenn man sich den Commit für Ausgabe Nr. 388 ansieht, ist die einzige Änderung eine neue Eigenschaft im Ansichtsfenster.

Wie würde ich das beabsichtigte Verhalten erhalten, das im GIF gezeigt wird, aber mit Ihren Änderungen?

Hallo @steprescott , versuchen Sie es mit [_chartView.viewPortHandler setMaximumScaleY: 2.f]; So ist beispielsweise die Granularität des Zooms nicht so groß, um wiederholte Werte anzuzeigen. Ein gutes Beispiel ist, wenn Sie eine horizontale Zeichenlinie ohne Begrenzung haben, werden alle Y-Werte wiederholt, wenn der Zoom groß ist. Bei MaximumScaleY kommt diese Wiederholung nicht vor.

Ohne Limit:
screen shot 2015-09-22 at 23 29 16

Mit Grenze 2f:
screen shot 2015-09-22 at 23 30 07

Hallo @noais

Das funktioniert bei einem Datensatz mit einem größeren Wertebereich, aber wenn Sie einen kleinen Wertebereich haben, z. B. ein Array mit Werten von 0 bis 7, kann das Vergrößern um den Faktor 2 möglicherweise doppelte Beschriftungen liefern.

Obwohl das Begrenzen des Zoomfaktors Ihr Problem gelöst hat, löst es nicht das Problem der Wiederholung ganzer Werte.

Ich habe meine erwarteten Ergebnisse erhalten, als ich die Klasse ChartYAxisRenderer bearbeitet habe, die auf Commit a7e30dd16fbfaecb8e44c01ad8618a3a745fd101 zeigt.

Dies wurde durch einen Flooring-Wert erreicht.

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

Obwohl dies funktioniert hat (aber nicht bei der Verwendung von HEAD dieses Repos), denke ich, dass Sie einen besseren Ort in Ihrem Rahmen kennen werden, um dies zu platzieren, um das gleiche Ergebnis wie im GIF gezeigt zu erzielen.

Vielleicht eine Eigenschaft allowRepeatingValues BOOL auf einer Achse. Ihr werdet es besser wissen.

Ja, Sie haben Recht, das war eine Umgehung. Lassen Sie mich versuchen zu sehen, ob es einfach ist, eine Methode wie allowRepeatingValues ​​zu erstellen.

Das wäre sehr hilfreich, danke.

Hallo @noais und @liuxuan30. Hatten Sie Gelegenheit, dies zu untersuchen? Ich konnte den erforderlichen Effekt mit dem Framework erzielen, aber ich weiß nicht, wo diese Eigenschaft am besten im Framework sitzen sollte und ob es einen besseren Weg gibt, dasselbe Ergebnis zu erzielen.

Vielen Dank für Ihre Zeit.

Ich denke immer noch, dass es daran liegt, dass der Formatierer doppelte Etiketten mit kleinen Ziffern erzeugt hat, nicht der Algorithmus. Wenn Sie den Formatierer löschen, wird die Nummer korrekt angezeigt, oder?
Sie können es mit Ihrem Code lösen, aber ich bin mir nicht sicher, ob es für jeden gut ist.
@danielgindi was denkst du

Hallo Leute, ich stimme für allowRepeatingValues, ich habe kleine Zahlen und möchte keinen doppelten Y-Achsenwert anzeigen

Wenn alle meine Werte Null sind, erhalte ich diese sich wiederholenden Achsenbeschriftungen.
chart

Außerdem ist mir aufgefallen, dass das Code-Snippet, das ich habe, zwar das tut, was ich brauche, aber keine doppelten Werte entfernt, sondern nur ganze Zahlen zulässt. Die Überprüfung mit dem Zahlenformatierer ist also keine schreckliche Methode, dies hinzuzufügen.

Was dieses Snippet nicht zulässt, ist das Entfernen doppelter Werte. Wenn die Werte also 1.1, 1.2, 1.2, 1.3 wären und Sie die einzelne Dezimalziffer beibehalten möchten, würde dies nicht funktionieren. Ihr werdet den besten Ort und die beste Implementierung für dieses Feature kennen, und für Leute, die Zeit damit verbringen, sich mit den aktuellen Problemen des Frameworks zu befassen, und damit sie dann abstimmen können, zeigt dies, dass es eine Option ist, die andere auch wollen.

AllowRepeatingValues ​​:+1:

@noais @liuxuan30 Hast du dafür eine bessere Lösung als die, die ich vorgeschlagen habe?

nein, außer allowRepeatingValues ​​.. Weil Ihr ursprüngliches Problem die Formatierer betrifft. Sie möchten keine Dezimalziffern auf einer Ebene, aber Ihre Daten haben tatsächlich die nächste Ebene

Idealerweise sollte das Diagramm niemals sich wiederholende Werte zeigen! Können sich wiederholende Werte mit einiger Logik ausgeblendet werden, sodass nur eindeutige Werte entstehen?

@vigyanhoon Es werden keine Werte dahinter "wiederholt", es ist ein Formatierer, der bewirkt, dass der Wert "wiederholt" wird. Wenn Sie keine Wiederholung wünschen, geben Sie einen Dezimalformatierer, der dies lösen kann.

@liuxuan30 Kannst du erklären, was du mit "_give a decimal formatter_" meinst? Mit meinen Daten habe ich einen Formatierer gegeben, der die maximumFractionDigits = 0 gesetzt hat. Ich bin mir nicht sicher, wie ich mit dem, was derzeit vorhanden ist, die erwarteten Ergebnisse erzielen kann? Konnten Sie mit dem Framework ein Diagramm erstellen, das die gleichen Ergebnisse liefert wie mein GIF, das ich am 28. August gepostet habe?

Wollten Sie numberFormatter.allowsFloats = NO verwenden, wenn ja, hat es mir nicht geholfen, ich sehe immer noch doppelte INTs?! Die einzige Möglichkeit, sich wiederholende Werte NICHT anzuzeigen, besteht darin, 2 Beschriftungen auf xAxis (oben / unten) zu verwenden.

@steprescott Entschuldigung, wenn ich nicht klar bin. MaximumFractionDigits sollte nicht 0 sein, sonst wird nur der ganzzahlige Teil angezeigt. Ich bin auf ähnliche Probleme gestoßen, wenn der Datenbereich klein ist und 5 bis 6 Beschriftungen benötigt werden, wird die Angabe von maximumFractionDigits = 0 wiederholte Werte haben. Es gibt keine einfache Möglichkeit, dies zu beheben, denke ich. Denken Sie darüber nach, ob der Datenbereich [0,2] ist und ich 5 Labels anzeigen muss: 0, 0,4, 0,8, 1,2, 1,6, 2,0. Wenn wir maximumFractionDigits = 0 anwenden, ist es vielleicht 0, 0, 1, 1, 2, 2

@injectios , wie wäre es mit MaximumFractionDigits = 2 oder sogar 4?

Hallo alle miteinander!
Ich habe das gleiche Problem.

@liuxuan30 Abhängig von der Art der Daten ist es nicht sinnvoll, Dezimalstellen zu haben. Wie in einem Menschenhoroskop werden Sie niemals 1,5 Menschen haben, es ist entweder 1 oder 2.

@jpros du hast einen Punkt, aber aus mathematischer Sicht können wir keine 4 Labels ohne Dezimalstellen im Bereich [0,2] haben.

Schalten Sie also entweder yAxis.showOnlyMinMaxEnabled ein, um wiederholte Werte zu vermeiden, als Workaround für den Moment,
Oder Sie implementieren Ihre Logik, um Ihre eigenen Werte in ChartYAxisRenderer.computeAxis zu berechnen, um zu vermeiden,
Oder wir müssen auf das Feature 'allowRepeatValues' warten

@PhilJay haben wir dafür derzeit eine Lösung? :-)

Von einem Android (und ofc iOS) POV, diese Zeile hier: https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java#L108

Könnte ein Ort sein, um dieses Problem anzugehen. Dort haben die float interval der Achsenbeschriftungen berechnet und könnten damit weitere Änderungen an den Beschriftungen verhindern, wenn zwei Beschriftungen gleich formatiert wären.
Das kommt mir gerade in den Sinn, wenn ich schnell darüber nachdenke. Was denken Sie?

Ich habe die Duplizierung beseitigt, indem ich einen Maximalwert festgelegt habe

leftAxis.customAxisMax = maxYLabelCount

@vigyanhoon , es ist eine ganz andere Sache, Werte könnten Millionen sein, während maxYLabelCount dies nicht kann. customAxisMax soll den maximalen Wert definieren, den der Achsenbereich haben könnte.

+1 für die Lösung des Rendering-Problems. Ich habe auch ein Diagramm von Menschen, und ich habe [0, 0, 1, 1, 2, 2]. Das Setzen von numberFormatter.maximumFractionDigits auf etwas anderes als 0 macht keinen Sinn.

Der folgende von @steprescott vorgeschlagene Code wurde auch für mich behoben. Ich habe es in meinem Fork hier hinzugefügt:

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

Wäre ein PR in der Lage, dieses Problem zu schließen? Was denkst du @danielgindi @liuxuan30 @steprescott ? Gibt es Fälle, die dieser Code nicht behebt? Wenn ja, was sind bessere Lösungen?

@natanrolnik Was ist, wenn der Benutzer hineinzoomt und die Reichweite zu [25.2, 25.3] wird? Das Intervall wäre 1,0, obwohl es beispielsweise 0,02 sein sollte.
Es sollte hilfreich sein, wenn der Benutzer die maximale Bruchzahl auf 0 setzt, wir begrenzen das Intervall. Negative Werte habe ich aber nicht getestet.
Wir haben noch keine bessere Lösung, aber ich schätze, ein Feature wie 'allowRepeatValues' ist das, was uns einfällt?

Ich stimme bezüglich allowRepeatedValues zu!

Ich denke, der @steprescott ist eine gute Lösung. Es muss nur der Wert eins an eine Granularitätsvariable angepasst werden.

Mit diesem @liuxuan30 existiert das Problem nicht mehr.

Wenn wir diesen Code in Zeile 75 in ChartYAxisRenderer einfügen:

interval = interval < granuality ? granuality : interval       

https://github.com/noais/ios-charts/compare/master...Noais
Was denken Sie?

Ok, das ist jetzt geschlossen, aber es ist nicht mit dem Master zusammengeführt. Wann würde dies voraussichtlich geschehen?

Dies wird in 2.2.4 als Funktion granularity veröffentlicht

Ich bin mir nicht sicher, ob ich dieses Problem hier posten soll, aber es macht für mich Sinn.

Ich habe ein sehr ähnliches Problem mit meinen xAxis-Etiketten. Ich habe einen benutzerdefinierten IAxisValueFormatter, der Zeichenfolgen für die Zeit zurückgibt, es gibt Stunden wie diese "22:00", "23:00" für einige Diagramme, Wochentage wie diese "Mon.", "Do." für andere usw..

Wenn das Diagramm zu stark vergrößert wird, beginnen sich die Werte zu duplizieren, wie hier gezeigt:

Screenshot 2019-07-19 at 17 59 11

In diesem Fall funktioniert die Funktion granularity nicht, da sie mit der Differenz zwischen Zahlen arbeitet.

Haben Sie eine Idee, wie ich verhindern könnte, dass sich diese Etiketten wiederholen?

Danke

Setzen Sie granularityEnabled auf false work for me
leftAxis.granularityEnabled = true

Hallo Leute, ich möchte, dass sich der xAxis-Wert beim Vergrößern nicht wiederholt
Mein Formatierer:
func stringForValue(_ value: Double, axis: AxisBase?) -> String {
let date = Date(timeIntervalSince1970: value)
return date.formattedString (withDateFormat: .daymonth)
}
Ich verwende auch Granularity, aber ich habe immer noch das gleiche Problem
xAchse.granularität = 1,0
xAxis.granularityEnabled = wahr

kann jemand wissen, wie man es löst, plz?

@Aimek
Ich habe das gleiche Problem, hast du die Lösung gefunden?

Ich habe das gleiche Problem, wenn ich die Anzahl der X-Achsen-Etiketten erzwinge und ein paar Punkte zeichne.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

cilasgimenez picture cilasgimenez  ·  4Kommentare

PrashantKT picture PrashantKT  ·  3Kommentare

guoyutaog picture guoyutaog  ·  3Kommentare

Shunshine07 picture Shunshine07  ·  3Kommentare

heumn picture heumn  ·  3Kommentare