webentwicklung-frage-antwort-db.com.de

Intelligente Platzierung der Punktbeschriftung in R

1) Gibt es eine R-Bibliothek/-Funktion, die die Platzierung von INTELLIGENT-Labels in R-Plots implementiert? Ich habe einige ausprobiert, aber sie sind alle problematisch - viele Beschriftungen überlappen einander oder andere Punkte (oder andere Objekte im Plot, aber ich sehe, dass dies viel schwieriger zu handhaben ist).

2) Wenn nicht, gibt es eine Möglichkeit, dem Algorithmus KOMFORTABEL bei der Platzierung der Beschriftung für bestimmte problematische Punkte zu helfen? Die komfortabelste und effizienteste Lösung.

Sie können andere Möglichkeiten mit meinem reproduzierbaren Beispiel spielen und testen und sehen, ob Sie bessere Ergebnisse erzielen können als ich:

# data
x = c(0.8846, 1.1554, 0.9317, 0.9703, 0.9053, 0.9454, 1.0146, 0.9012, 
0.9055, 1.3307)
y = c(0.9828, 1.0329, 0.931, 1.3794, 0.9273, 0.9605, 1.0259, 0.9542, 
0.9717, 0.9357)
ShortSci = c("MotAlb", "PruMod", "EriRub", "LusMeg", "PhoOch", "PhoPho", 
"SaxRub", "TurMer", "TurPil", "TurPhi")

# basic plot
plot(x, y, asp=1)
abline(h = 1, col = "green")
abline(v = 1, col = "green")

Zum Beschriften habe ich dann diese Möglichkeiten ausprobiert, niemand ist wirklich gut:

1) dieser ist schrecklich:

text(x, y, labels = ShortSci, cex= 0.7, offset = 10)

2) Dieser ist gut, wenn Sie nicht für alle Punkte Beschriftungen platzieren möchten, sondern nur für die Ausreißer. Dennoch werden die Beschriftungen häufig falsch platziert:

identify(x, y, labels = ShortSci, cex = 0.7)

3) Dieser sah vielversprechend aus, aber es gibt das Problem, dass die Etiketten zu nah an den Punkten sind. Ich musste sie mit Leerzeichen auffüllen, aber das hilft nicht viel:

require(maptools)
pointLabel(x, y, labels = paste("  ", ShortSci, "  ", sep=""), cex=0.7)

4)

require(plotrix)
thigmophobe.labels(x, y, labels = ShortSci, cex=0.7, offset=0.5)

5)

require(calibrate)
textxy(x, y, labs=ShortSci, cx=0.7)

Danke im Voraus!

EDIT: todo: try labcurve {Hmisc} .

100
TMS

Ich habe eine Lösung gefunden! Es ist leider nicht ultimativ und ideal, aber es funktioniert jetzt am besten für mich. Es ist halb algoritmisch, halb manuell, daher spart es Zeit im Vergleich zu einer reinen manuellen Lösung, die von joran entworfen wurde.

Ich habe sehr übersehen wichtiger Teil der ?identify - Hilfe!

Der zum Platzieren von Beschriftungen verwendete Algorithmus ist derselbe, der auch von Text verwendet wird, wenn dort pos angegeben ist. Der Unterschied besteht darin, dass die Position des Zeigers relativ zum identifizierten Punkt pos in identity bestimmt.

Wenn Sie also die identify() -Lösung verwenden, wie ich sie in meiner Frage geschrieben habe, dann Sie können die Position der Beschriftung beeinflussen, indem Sie nicht direkt auf diesen Punkt klicken, sondern durch relativ in die gewünschte Richtung neben diesen Punkt klicken !!! Funktioniert einfach super!

Der Nachteil ist, dass es nur 4 Positionen gibt (oben, links, unten, rechts), aber ich würde die anderen 4 (oben links, oben rechts, unten links, unten rechts) mehr schätzen ... Also ich benutze dies, um Punkte zu kennzeichnen, die mich nicht stören, und die restlichen Punkte, die ich direkt in meiner PowerPoint-Präsentation beschrifte, wie von joran vorgeschlagen :-)

PS: Ich habe die DirectLabels-Lösung für Gitter/GG-Plots noch nicht ausprobiert. Ich bevorzuge weiterhin die grundlegende Plotbibliothek.

5
TMS

Hier sind die Ergebnisse meiner Lösung für dieses Problem:

enter image description here

Ich habe dies in der Vorschau (sehr einfacher PDF/Bildbetrachter unter OS X) von Hand in wenigen Minuten erledigt. ( Bearbeiten: Der Workflow war genau das, was Sie erwartet hatten: Ich speicherte den Plot als PDF aus R, öffnete es in der Vorschau und erstellte Textfelder mit den gewünschten Bezeichnungen (9pt Helvetica) und zog sie dann einfach mit der Maus herum, bis sie gut aussahen. Dann exportierte ich sie in ein PNG zum Hochladen auf SO.)

Bevor Sie nun dem starken Drang nach Abwärtsstimmen in Vergessenheit geraten und scharfsinnige Kommentare dazu hinterlassen, wie es darum geht, diesen Prozess zu automatisieren, hören Sie mir zu!

Die Suche nach algorithmischen Lösungen ist völlig in Ordnung und (meiner Meinung nach) wirklich interessant. Punktkennzeichnungssituationen lassen sich für mich jedoch in ungefähr drei Kategorien einteilen:

  1. Sie haben eine kleine Anzahl von Punkten, keine, die furchtbar nahe beieinander liegen . In diesem Fall ist es wahrscheinlich, dass eine der von Ihnen in der Frage aufgelisteten Lösungen nur mit minimaler Optimierung funktioniert.
  2. Sie haben eine kleine Anzahl von Punkten, von denen einige für die typischen algorithmischen Lösungen zu dicht gepackt sind, um gute Ergebnisse zu erzielen . In diesem Fall ist das Beschriften von Hand (entweder mit einem Bildeditor oder durch Feinabstimmung Ihres Aufrufs auf text) nicht , da Sie nur über eine geringe Anzahl von Punkten verfügen. das viel Aufwand.
  3. Sie haben eine ziemlich große Anzahl von Punkten . In diesem Fall sollten Sie sie sowieso nicht kennzeichnen, da es schwierig ist, eine große Anzahl von Etiketten visuell zu verarbeiten.

: Klettern auf Seifenkiste:

Da Leute wie wir die Automatisierung lieben , sind wir meiner Meinung nach häufig der Meinung, dass nahezu jeder Aspekt der Erstellung einer guten statistischen Grafik automatisiert werden sollte. Ich bin respektvoll (demütig!) Anderer Meinung.

Es gibt keine vollkommen allgemeine statistische Plot-Umgebung, die das Bild, das Sie in Ihrem Kopf haben, automatisch erzeugt. Dinge wie R, ggplot2, Gitter usw. machen den größten Teil der Arbeit ; Aber dieses zusätzliche kleine Feineinstellen, Hinzufügen einer Linie hier und Anpassen eines Rands dort, ist wahrscheinlich besser für ein anderes Werkzeug geeignet.

: Klettern aus der Seifenkiste:

Ich würde auch bemerken, dass ich denke, dass wir alle Streudiagramme mit <10-15 Punkten entwickeln könnten, die sich selbst von Hand kaum sauber etikettieren lassen, und diese werden wahrscheinlich jede automatische Lösung brechen, die jemandem einfällt.

Schließlich möchte ich wiederholen, dass ich weiß , dass dies nicht die Antwort ist, die Sie suchen. Und ich sage nicht , dass algorithmische Versuche nutzlos oder dumm sind. Ich habe diese Frage positiv bewertet und werde gerne interessante algorithmische Lösungen positiv bewerten!

Der Grund, warum ich diese Antwort gepostet habe, ist, dass ich denke, dass diese Frage die kanonische "Punktekennzeichnung in R" -Frage für zukünftige Duplikate sein sollte, und ich denke, dass Lösungen mit Handkennzeichnung einen Platz am Tisch verdienen, das ist alles.

47
joran

ggrepel sieht vielversprechend aus, wenn es auf ggplot2 - Streudiagramme angewendet wird.

# data
x = c(0.8846, 1.1554, 0.9317, 0.9703, 0.9053, 0.9454, 1.0146, 0.9012, 
0.9055, 1.3307)
y = c(0.9828, 1.0329, 0.931, 1.3794, 0.9273, 0.9605, 1.0259, 0.9542, 
0.9717, 0.9357)
ShortSci = c("MotAlb", "PruMod", "EriRub", "LusMeg", "PhoOch", "PhoPho", 
"SaxRub", "TurMer", "TurPil", "TurPhi")


df <- data.frame(x = x, y = y, z = ShortSci)
library(ggplot2)
library(ggrepel)

ggplot(data = df, aes(x = x, y = y)) + theme_bw() + 

    geom_text_repel(aes(label = z), 
       box.padding = unit(0.45, "lines")) +

    geom_point(colour = "green", size = 3)

enter image description here

39
Sandy Muspratt

Haben Sie das Paket directlabels ausprobiert?

Übrigens können die Argumente pos und offset Vektoren enthalten, damit Sie sie an die richtigen Positionen bringen können, wenn in nur wenigen Durchläufen eine angemessene Anzahl von Punkten vorhanden ist.

10
John

Ich würde vorschlagen, dass Sie sich das Paket wordcloud ansehen. Ich weiß, dass sich dieses Paket nicht genau auf die Punkte konzentriert, sondern auf die Etiketten selbst, und auch der Stil scheint eher festgelegt zu sein. Trotzdem waren die Ergebnisse, die ich damit erzielt habe, ziemlich beeindruckend. Beachten Sie auch, dass die betreffende Paketversion zu dem Zeitpunkt veröffentlicht wurde, an dem Sie die Frage gestellt haben. Sie ist also noch sehr neu.

http://blog.fellstat.com/?cat=11

4
maj

Ich habe eine R-Funktion namens addTextLabels() innerhalb eines Pakets plotteR geschrieben. Das Paket kann mit dem folgenden Code direkt in Ihrer R-Bibliothek installiert werden:

install.packages("devtools")
library("devtools")
install_github("JosephCrispell/basicPlotteR")

Für das bereitgestellte Beispiel habe ich den folgenden Code verwendet, um die unten verlinkte Beispielabbildung zu generieren.

# Load the plotteR library
library(plotteR)

# Create vectors storing the X and Y coordinates
x = c(0.8846, 1.1554, 0.9317, 0.9703, 0.9053, 0.9454, 1.0146, 0.9012, 
      0.9055, 1.3307)
y = c(0.9828, 1.0329, 0.931, 1.3794, 0.9273, 0.9605, 1.0259, 0.9542, 
      0.9717, 0.9357)

# Store the labels to be plotted in a vector
ShortSci = c("MotAlb", "PruMod", "EriRub", "LusMeg", "PhoOch", "PhoPho", 
             "SaxRub", "TurMer", "TurPil", "TurPhi")

# Plot the X and Y coordinates without labels
plot(x, y, asp=1)
abline(h = 1, col = "green")
abline(v = 1, col = "green")

# Add non-overlapping text labels
addTextLabels(x, y, ShortSci, cex=0.9, col.background=rgb(0,0,0, 0.75), 
              col.label="white")

Dabei wird automatisch ein alternativer Ort aus einem feinen Punktegitter ausgewählt. Die nächstgelegenen Punkte im Raster werden zuerst besucht und ausgewählt, wenn sie sich nicht mit geplotteten Punkten oder Beschriftungen überschneiden. Werfen Sie einen Blick auf die Quelle Code , wenn Sie interessiert sind.

Example Figure

3
Joseph Crispell

Keine Antwort, aber zu lang für einen Kommentar. Ein sehr einfacher Ansatz, der in einfachen Fällen zwischen der Nachbearbeitung durch joran und den vorgestellten komplexeren Algorithmen funktioniert, besteht darin, in-place Einfache Transformationen des Datenrahmens vorzunehmen.

Ich illustriere dies mit ggplot2, Da ich mit dieser Syntax besser vertraut bin als mit Basis-R-Plots.

df <- data.frame(x = x, y = y, z = ShortSci)
library("ggplot2")
ggplot(data = df, aes(x = x, y = y, label = z)) + theme_bw() + 
    geom_point(shape = 1, colour = "green", size = 5) + 
    geom_text(data = within(df, c(y <- y+.01, x <- x-.01)), hjust = 0, vjust = 0)

Wie Sie sehen, ist das Ergebnis in diesem Fall nicht ideal, kann aber für einige Zwecke gut genug sein. Und es ist ziemlich mühelos, normalerweise reicht so etwas within(df, y <- y+.01)

enter image description here

2
PatrickT