2016-01-12 13 views
14

Ich verwende facet_grid(), um einige Daten anzuzeigen, und ich habe Facettenlabels, die sich über mehrere Textzeilen erstrecken (sie enthalten das "\ n" -Zeichen).ggplot2: Wie kann man Text von mehrzeiligen Facettenlabels linksbündig ausrichten?

require(ggplot2) 

#Generate example data 
set.seed(3) 
df = data.frame(facet_label_text = rep(c("Label A", 
             "Label B\nvery long label", 
             "Label C\nshort", 
             "Label D"), 
             each = 5), 
       time = rep(c(0, 4, 8, 12, 16), times = 4), 
       value = runif(20, min=0, max=100)) 

#Plot test data 
ggplot(df, aes(x = time, y = value)) + 
    geom_line() + 
    facet_grid(facet_label_text ~ .) + 
    theme(strip.text.y = element_text(angle = 0, hjust = 0)) 

So durch die hjust = 0 Argument verwendet wird, kann ich links-align Facette Beschriftungstext als eine Einheit.

enter image description here

Was Ich mag würde, ist zu tun, linksbündig auszurichten jede einzelne Textzeile. So sind "Label B" und "sehr langes Label" beide auf der linken Seite ausgerichtet, anstatt zueinander zentriert zu sein (ebenso für "Label C" und "Short"). Ist das in ggplot2 möglich? Vielen Dank im Voraus für Ihre Hilfe.

Antwort

8

Diese ist recht unkompliziert grid.gedit Funktion mit Gittern, die Streifen zu bearbeiten.

library(ggplot2) # v2.1.0 
library(grid) 

# Your data 
set.seed(3) 
df = data.frame(facet_label_text = rep(c("Label A", 
             "Label B\nvery long label", 
             "Label C\nshort", 
             "Label D"), 
             each = 5), 
       time = rep(c(0, 4, 8, 12, 16), times = 4), 
       value = runif(20, min=0, max=100)) 

# Your plot 
p = ggplot(df, aes(x = time, y = value)) + 
    geom_line() + 
    facet_grid(facet_label_text ~ .) + 
    theme(strip.text.y = element_text(angle = 0, hjust = 0)) 
p 

# Get a list of grobs in the plot 
grid.ls(grid.force()) 

# It looks like we need the GRID.text grobs. 
# But some care is needed: 
# There are GRID.text grobs that are children of the strips; 
# but also there are GRID.text grobs that are children of the axes. 
# Therefore, a gPath should be set up 
# to get to the GRID.text grobs in the strips 

# The edit 
grid.gedit(gPath("GRID.stripGrob", "GRID.text"), 
     just = "left", x = unit(0, "npc")) 

Oder noch ein paar Zeilen Code mit einem grob Objekt (anstelle der Bearbeitung auf dem Bildschirm wie oben) zu arbeiten:

# Get the ggplot grob 
gp = ggplotGrob(p) 
grid.ls(grid.force(gp)) 

# Edit the grob 
gp = editGrob(grid.force(gp), gPath("GRID.stripGrob", "GRID.text"), grep = TRUE, global = TRUE, 
      just = "left", x = unit(0, "npc")) 

# Draw it 
grid.newpage() 
grid.draw(gp) 

enter image description here

+0

Danke für die tolle Antwort. Es scheint, dass es eine Menge Kraft darin gibt, zu wissen, wie man das Grid und Grob-Objekte, die ggplot zugrunde liegen, verändert. Kannst du eine gute Einsteiger-Ressource oder Anleitung für die Grid/Grob-Bearbeitung empfehlen? Danke noch einmal. –

+1

Nachdem ich etwas damit herumgespielt habe, denke ich, dass man den Grob holen kann, ohne ihn zuerst mit diesem kleinen Tweak anzeigen zu müssen: 'grab = grid.grabExpr (grid.draw (gp))' –

+0

@Brain_Food AFAIK, da ist nichts bringt die Grid-Bearbeitung von ggplot2-Graphen auf eine umfassende Art und Weise zusammen. Für "Grid", überprüfen Sie die Referenzen auf der Info-Seite von "r-Grid" Tag auf SO. [Paul Murrells Workshop UseR 2015] (https://www.stat.auckland.ac.nz/~paul/useR2015-grid/) geben einige Details zur Bearbeitung von ggplots mithilfe von Rasterfunktionen. Sonst antwortet SO. Außerdem sind 'gtable'-Funktionen nützlich. Baptiste hat [einige Anmerkungen zu 'gtable'] zusammengestellt (https://github.com/baptiste/gtable/wiki/Description) –

7

Bis jemand mit einer echten Lösung kommt, hier ist ein Hack: Fügen Sie Platz in den Etiketten, um die gewünschte Begründung zu erhalten.

require(ggplot2) 

#Generate example data 
set.seed(3) 
df = data.frame(facet_label_text = rep(c("Label A", 
             "Label B   \nvery long label", 
             "Label C\nshort  ", 
             "Label D"), 
             each = 5), 
       time = rep(c(0, 4, 8, 12, 16), times = 4), 
       value = runif(20, min=0, max=100)) 

#Plot test data 
ggplot(df, aes(x = time, y = value)) + 
    geom_line() + 
    facet_grid(facet_label_text ~ .) + 
    theme(strip.text.y = element_text(angle = 0, hjust = 0)) 

enter image description here

5

kann ein sauberer Weg, dies zu tun, aber ich habe nicht einen Weg, dies zu tun in ggplot2 finden. Die padwrap Funktion könnte generalisierter sein, da sie im Grunde genau das ist, was Sie angefordert haben. Um die Rechtfertigung richtig zu machen, musste ich eine mono-spaced Schriftart verwenden.

# Wrap text with embedded newlines: space padded and lef justified. 
# There may be a cleaner way to do this but this works on the one 
# example. If using for ggplot2 plots, make the font `family` 
# a monospaced font (e.g. 'Courier') 
padwrap <- function(x) { 
    # Operates on one string 
    padwrap_str <- function(s) { 
     sres <- strsplit(s, "\n") 
     max_len <- max(nchar(sres[[1]])) 
     paste(sprintf(paste0('%-', max_len, 's'), sres[[1]]), collapse = "\n") 
    } 
    # Applys 'padwrap' to a vector of strings 
    unlist(lapply(x, padwrap_str)) 
} 

require(ggplot2) 

facet_label_text = rep(c("Label A", 
         "Label B\nvery long label", 
         "Label C\nshort", 
         "Label D"), 5) 
new_facet_label_text <- padwrap(facet_label_text) 

#Generate example data 
set.seed(3) 
df = data.frame(facet_label_text = new_facet_label_text, 
       time = rep(c(0, 4, 8, 12, 16), times = 4), 
       value = runif(20, min=0, max=100)) 

#Plot test data 
ggplot(df, aes(x = time, y = value)) + 
    geom_line() + 
    facet_grid(facet_label_text ~ .) + 
    theme(strip.text.y = element_text(angle = 0, hjust = 0, family = 'Courier')) 

Der Streifen Text ist unter

im Bild linksbündig

enter image description here

+0

Clever Idee. Vielleicht könnten Sie es auf nicht mono-distanzierte Schriften verallgemeinern. Verwenden Sie 'strwidth', um die relativen Größen jedes Zeichens zu ermitteln, und verwenden Sie dann diese Option, um den für jede Zeichenfolge erforderlichen Abstand festzulegen. Zum Beispiel: 'strwidth (c (LETTERS, letters," "), units =" inches ", family =" Times ")' gibt Ihnen die Breite aller Groß- und Kleinbuchstaben plus ein Leerzeichen in der Schriftart * Times * . – eipi10

+0

@ eipi10 Ich wusste nicht über 'strwidth'. Wenn ich etwas Zeit habe, werde ich es implementieren und sehen, wie es funktioniert (es sei denn, jemand schlägt mich dazu). Ich habe mich gefragt, wie man die Breite von nicht mono-spaced Schriften bekommen würde; Ihr Vorschlag löst das (vorausgesetzt, strwidth funktioniert, wie wir hoffen). – steveb

+0

Probieren Sie diese "plot (strwidth (c (Buchstaben, Buchstaben," "), Einheiten =" Zoll ", Familie =" Times "), 1:53, pch = c (Buchstaben, Buchstaben," ")) und dies 'plot (strwidth (c (LETTERS, Buchstaben," "), units =" Zoll ", family =" Courier "), 1:53, pch = c (Buchstaben, Buchstaben," "))' und ein paar andere Schriftarten und Sie können die Variation der Zeichenbreite sehen (oder nicht für Courier). – eipi10

Verwandte Themen