Was ist der richtige Algorithmus für eine logarithmische Verteilungskurve zwischen zwei Punkten?

StackOverflow https://stackoverflow.com/questions/604953

  •  03-07-2019
  •  | 
  •  

Frage

Ich habe eine Reihe von Tutorials über die richtige Art und Weise zu lesen eine logarithmische Verteilung der tagcloud Gewichte zu erzeugen. Die meisten von ihnen Gruppe die Tags in Schritten. Dies scheint ein wenig albern zu mir, so entwickelte ich meine eigenen Algorithmus auf das, was ich gelesen habe, so dass es dynamisch die Tag-Zählung entlang der logarthmic Kurve zwischen der Schwelle und dem maximalen verteilt. Hier ist die Essenz davon in Python:

from math import log
count = [1, 3, 5, 4, 7, 5, 10, 6]
def logdist(count, threshold=0, maxsize=1.75, minsize=.75):
    countdist = []
    # mincount is either the threshold or the minimum if it's over the threshold
    mincount = threshold<min(count) and min(count) or threshold
    maxcount = max(count)
    spread = maxcount - mincount
    # the slope of the line (rise over run) between (mincount, minsize) and ( maxcount, maxsize)
    delta = (maxsize - minsize) / float(spread)
    for c in count:
        logcount = log(c - (mincount - 1)) * (spread + 1) / log(spread + 1)
        size = delta * logcount - (delta - minsize)
        countdist.append({'count': c, 'size': round(size, 3)})
    return countdist

Grundsätzlich ohne die logarithmische Berechnung der einzelnen Zählwert, wäre es eine gerade Linie zwischen den Punkten, (mincount, MinSize) und (MaxCount, maxsize) erzeugen.

Der Algorithmus hat eine gute Näherung der Kurve zwischen den beiden Punkten, leidet aber unter einem Nachteil. Die mincount ist ein Sonderfall, und der Logarithmus davon erzeugt Null. Dies bedeutet, dass die Größe des mincount als minsize weniger wäre. Ich habe versucht, Zahlen Kochen bis zu versuchen, diesen speziellen Fall zu lösen, kann aber nicht scheinen, um es richtig zu machen. Derzeit behandel ich nur die mincount als Sonderfall und füge „or 1“ die logcount Linie.

Gibt es einen richtigen Algorithmus eine Kurve zwischen den beiden Punkten zu ziehen?

Update 3. März : Wenn ich mich nicht irre, bin ich das Protokoll der Zählung zu nehmen und sie dann in eine lineare Gleichung zu verstopfen. Um die Beschreibung des speziellen Falles in anderen Worten ausgedrückt, in y = lnx bei x = 1, y = 0. Dies ist, was am mincount passiert. Aber die mincount nicht Null sein kann, hat der Tag nicht 0 Mal verwendet.

Versuchen Sie den Code und Stecker in Ihren eigenen Zahlen zu testen. Die Behandlung der mincount als Spezialfall ist für mich in Ordnung, habe ich das Gefühl es einfacher als das, was für dieses Problem die eigentliche Lösung wäre. Ich fühle mich einfach wie es muss eine Lösung für dieses sein und dass jemand wahrscheinlich mit einer Lösung kommen.

UPDATE 6. April : Ein einfaches google Suche schaltet sich ein viele der Tutorials bis ich gelesen habe, aber diese wahrscheinlich das vollständigste Beispiel gestuften Tag-clouds.

UPDATE 28. April : Als Antwort auf antti.huima Lösung: Wenn grafisch dargestellt, die Kurve, dass Ihr Algorithmus liegt unterhalb der Linie zwischen den beiden Punkten erzeugt. Ich habe versucht, die Zahlen um zu jonglieren, aber immer noch nicht mit einer Art und Weise zu kommen scheinen, daß die Kurve auf die andere Seite der Linie zu kippen. Ich vermute, dass, wenn die Funktion zu irgendeiner Form von Logarithmus anstelle einem Exponenten geändert wurde es genau tun würde, was ich brauchen würde. Ist das korrekt? Wenn ja, kann jemand erklären, wie dies zu erreichen?

War es hilfreich?

Lösung

Dank antti.huima Hilfe, ich neu durchdacht, was ich tun wollte.

Unter seiner Methode das Problem zu lösen, mag ich eine Gleichung, wo der Logarithmus des mincount auf die lineare Gleichung zwischen den beiden Punkten gleich ist.

weight(MIN) = ln(MIN-(MIN-1)) + min_weight
min_weight = ln(1) + min_weight

Während dieser mir einen guten Ausgangspunkt gibt, muss ich es durch den Punkt (MAX, max_weight) Pass. Es wird eine Konstante müssen:

weight(x) = ln(x-(MIN-1))/K + min_weight

Solving für K erhalten wir:

K = ln(MAX-(MIN-1))/(max_weight - min_weight)

Also, das alles wieder in einen Python-Code zu setzen:

from math import log
count = [1, 3, 5, 4, 7, 5, 10, 6]
def logdist(count, threshold=0, maxsize=1.75, minsize=.75):
    countdist = []
    # mincount is either the threshold or the minimum if it's over the threshold
    mincount = threshold<min(count) and min(count) or threshold
    maxcount = max(count)
    constant = log(maxcount - (mincount - 1)) / (maxsize - minsize)
    for c in count:
        size = log(c - (mincount - 1)) / constant + minsize
        countdist.append({'count': c, 'size': round(size, 3)})
    return countdist

Andere Tipps

Lassen Sie sich mit Ihrer Abbildung von der angemeldeten Zählung der Größe beginnen. Das ist die lineare Abbildung Sie erwähnt:

   size
    |
max |_____
    |   /
    |  /|
    | / |
min |/  |
    |   |
   /|   |
0 /_|___|____
    0   a

wobei min und max sind die min und max Größen und a = log (maxcount) -b. Die Linie ist y = mx + c wobei x = log (count) -B

Aus dem Diagramm können wir, dass die Steigung, m sehen ist (maxsize-minsize) / a.

Wir brauchen x = 0 bei y = minsize, so log (mincount) -b = 0 -> b = log (mincount)

Dies lässt uns mit folgendem Python:

mincount = min(count)
maxcount = max(count)
xoffset = log(mincount)
gradient = (maxsize-minsize)/(log(maxcount)-log(mincount))
for c in count:
    x = log(c)-xoffset
    size = gradient * x + minsize

Wenn Sie sicherstellen möchten, dass die Mindestanzahl ist immer mindestens 1 ist, ersetzen Sie die erste Zeile mit:

mincount = min(count+[1])

, die 1 bis der Zählliste anhängt, bevor Sie min zu tun. Das gleiche gilt, dass er die maxcount ist immer mindestens 1 also Ihr endgültiger Code pro oben ist:

from math import log
count = [1, 3, 5, 4, 7, 5, 10, 6]
def logdist(count, maxsize=1.75, minsize=.75):
    countdist = []
    mincount = min(count+[1])
    maxcount = max(count+[1])
    xoffset = log(mincount)
    gradient = (maxsize-minsize)/(log(maxcount)-log(mincount))
    for c in count:
        x = log(c)-xoffset
        size = gradient * x + minsize
        countdist.append({'count': c, 'size': round(size, 3)})
    return countdist

, was Sie haben, ist, dass Sie Tags, die Zählungen von MIN bis MAX haben; die Schwellen Problem hier außer Acht gelassen werden kann, weil es jede Zählung Einstellung unter dem Schwellenwert auf den Schwellenwert und unter den minimalen und maximalen erst danach.

beträgt

Sie wollen den Tag zählt zur Karte zu „Gewichte“, sondern in einem „logarithmisch“, was im Grunde bedeutet die folgende (wie ich es verstehe). Zunächst erhalten die Tags mit Zahl MAX max_weight Gewicht (in Ihrem Beispiel, 1,75):

weight(MAX) = max_weight

Zum anderen werden die Tags mit der Zählung MIN erhalten min_weight Gewicht (in Ihrem Beispiel, 0,75):

weight(MIN) = min_weight

Schließlich gilt, dass, wenn Ihre Zählung um 1 abnimmt, wird das Gewicht mit einer Konstanten K multipliziert <1, der die Steilheit der Kurve zeigt an:

weight(x) = weight(x + 1) * K

Die Lösung dieses, erhalten wir:

weight(x) = weight_max * (K ^ (MAX - x))

Beachten Sie, dass mit x = MAX, der Exponent Null und der Multiplikand auf der rechten Seite wird 1.

Jetzt haben wir die zusätzliche Anforderung, dass das Gewicht (MIN) = min_weight, und wir können lösen:

weight_min = weight_max * (K ^ (MAX - MIN))

, von dem wir bekommen

K ^ (MAX - MIN) = weight_min / weight_max

und unter Logarithmus auf beiden Seiten

(MAX - MIN) ln K = ln weight_min - ln weight_max

d.

ln K = (ln weight_min - ln weight_max) / (MAX - MIN)

Die rechte Seite negativ ist, wie gewünscht, weil K <1 ist dann

K = exp((ln weight_min - ln weight_max) / (MAX - MIN))

So, jetzt haben Sie die Formel K. zu berechnen Danach einfach für jede Zahl x zwischen MIN und MAX gelten:

weight(x) = max_weight * (K ^ (MAX - x))

Und du bist fertig.

Auf einer logarithmischen Skala, die Sie gerade das Protokoll der Zahlen zeichnen linear (in anderen Worten, so tun Sie linear sind Plotten, aber nehmen Sie das Protokoll der Zahlen zu plottenden zuerst).

Das Null Problem kann nicht analytisch gelöst werden - Sie mindestens um eine Größenordnung für die Waage zu wählen haben, und egal, was Sie Null nicht immer erreichen können. Wenn Sie etwas auf Null darstellen möchten, sind Ihre Entscheidungen willkürlich geben sie die Mindest Größenordnung der Skala, oder es zu unterlassen.

Ich habe nicht die genaue Antwort, aber ich glaube, Sie wollen Linearisierungs Exponential Daten nachzuschlagen. Beginnen Sie mit der Berechnung der Gleichung der Geraden durch die Punkte und nehmen Sie das Protokoll von beiden Seiten dieser Gleichung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top