2016-05-10 8 views
24

Angenommen, ich habe folgendes Grundstück in ggplot:Wie Farbe, Linienstil und Form Legenden in ggplot verschmelzen

ggplot graph

Es erzeugt wurde unter Verwendung des Codes:

x <- seq(0, 10, by = 0.2) 
y1 <- sin(x) 
y2 <- cos(x) 
y3 <- cos(x + pi/4) 
y4 <- sin(x + pi/4) 
df1 <- data.frame(x, y = y1, Type = as.factor("sin"), Method = as.factor("method1")) 
df2 <- data.frame(x, y = y2, Type = as.factor("cos"), Method = as.factor("method1")) 
df3 <- data.frame(x, y = y3, Type = as.factor("cos"), Method = as.factor("method2")) 
df4 <- data.frame(x, y = y4, Type = as.factor("sin"), Method = as.factor("method2")) 

df.merged <- rbind(df1, df2, df3, df4) 

ggplot(df.merged, aes(x, y, colour = interaction(Type, Method), linetype = Method, shape = Type)) + geom_line() + geom_point() 

würde ich Ich möchte nur eine Legende haben, die die Formen, die Farben und die Linientypen korrekt anzeigt (die Interaktion (Typ, Methode) Legenden ist am nächsten zu dem, was ich möchte, aber es hat nicht die richtigen Formen/Linientypen).

Ich weiß, dass, wenn ich scale_xxx_manual verwenden und ich die gleichen Beschriftungen für alle Legenden angeben, werden sie zusammengeführt, aber ich möchte die Beschriftungen nicht manuell festlegen: Wenn es neue Methoden oder Typen gibt, ich don Ich möchte meinen Code ändern müssen: a wollen etwas Generisches.

bearbeiten

Wie unten Antworten darauf gibt es mehrere Möglichkeiten, um die Arbeit in diesem speziellen Fall getan. Alle vorgeschlagenen Lösungen erfordern die manuelle Festlegung der Legendientypen und -formen, entweder mithilfe der Funktion scale_xxx_manual function s oder mit der Funktion guides.

Die vorgeschlagenen Lösungen funktionieren jedoch im allgemeinen Fall immer noch nicht: Wenn ich beispielsweise einen neuen Datenrahmen mit einer neuen "method3" -Methode zum Datensatz hinzufüge, funktioniert das nicht mehr, wir müssen manuell hinzufügen die neue Legende Formen und Linientypen:

y5 <- sin(x - pi/4) 
df5 <- data.frame(x, y = y5, Type = as.factor("sin"), Method = as.factor("method3")) 
df.merged <- rbind(df1, df2, df3, df4, df5) 
override.shape <- c(16, 17, 16, 17, 16) 
override.linetype <- c(1, 1, 3, 3, 4) 

g <- ggplot(df.merged, aes(x, y, colour = interaction(Type, Method), linetype = Method, shape = Type)) + geom_line() + geom_point() 
g <- g + guides(colour = guide_legend(override.aes = list(shape = override.shape, linetype = override.linetype))) 
g <- g + scale_shape(guide = FALSE) 
g <- g + scale_linetype(guide = FALSE) 
print(g) 

das gibt:

5 curves

Nun ist die Frage: wie automatisch erzeugen die override.shape und override.linetype Vektoren?

Beachten Sie, dass die Vektorgröße 5 ist, weil wir 5 Kurven haben, während der interaction(Type, Method) Faktor Größe 6 (Ich habe keine Daten für die cos/method3 Kombination)

+1

Ihre Farbskala ist redundant zu den kombinierten Form- und Linientypskalen. Sie sollten nur einen von diesen verwenden. – Roland

+0

Ja, es ist redundant. Zuerst wurden Farben dem Typ und Linientyp der Methode zugeordnet. Aber dann, wenn Kurven zu nahe beieinander waren, war es schwer, sie auseinander zu halten. Daher ist die Redundanz – Ben

+1

Es ist oft angemessen, redundante Form-/Farbgruppendefinitionen zu haben. In vielen wissenschaftlichen Veröffentlichungen ist Farbe der visuell effektivste Weg, um Gruppen zu unterscheiden, aber Sie wissen auch, dass ein großer Teil der Leser Schwarz-Weiß-Kopien des Papiers drucken wird. Daher möchten Sie auch einen visuellen Hinweis einfügen, der nicht t abhängig von der Farbe. – neuropsych

Antwort

3

Hier ist die Lösung im allgemeinen Fall:

# Create the data frames 
x <- seq(0, 10, by = 0.2) 
y1 <- sin(x) 
y2 <- cos(x) 
y3 <- cos(x + pi/4) 
y4 <- sin(x + pi/4) 
y5 <- sin(x - pi/4) 
df1 <- data.frame(x, y = y1, Type = as.factor("sin"), Method = as.factor("method1")) 
df2 <- data.frame(x, y = y2, Type = as.factor("cos"), Method = as.factor("method1")) 
df3 <- data.frame(x, y = y3, Type = as.factor("cos"), Method = as.factor("method2")) 
df4 <- data.frame(x, y = y4, Type = as.factor("sin"), Method = as.factor("method2")) 
df5 <- data.frame(x, y = y5, Type = as.factor("sin"), Method = as.factor("method3")) 

# Merge the data frames 
df.merged <- rbind(df1, df2, df3, df4, df5) 

# Create the interaction 
type.method.interaction <- interaction(df.merged$Type, df.merged$Method) 

# Compute the number of types and methods 
nb.types <- nlevels(df.merged$Type) 
nb.methods <- nlevels(df.merged$Method) 

# Set the legend title 
legend.title <- "My title" 

# Initialize the plot 
g <- ggplot(df.merged, aes(x, 
          y, 
          colour = type.method.interaction, 
          linetype = type.method.interaction, 
          shape = type.method.interaction)) + geom_line() + geom_point() 
# Here is the magic 
g <- g + scale_color_discrete(legend.title) 
g <- g + scale_linetype_manual(legend.title, 
           values = rep(1:nb.types, nb.methods)) 
g <- g + scale_shape_manual(legend.title, 
          values = 15 + rep(1:nb.methods, each = nb.types)) 
# Display the plot 
print(g) 

Das Ergebnis ist folgendes:

The solution

  • Sinus-Kurve s sind als durchgezogene Linien und Cosinus-Kurven als gestrichelte Linien gezeichnet.
  • "method1" Daten verwenden gefüllte Kreise für die Form.
  • "method2" Daten verwenden gefülltes Dreieck für die Form.
  • "method3" Daten verwenden gefüllte Diamanten für die Form.
  • Die Legende entspricht die Kurve

Zusammenfassend sind die Tricks:

  • die Art/Methode interaction für alle Datendarstellungen verwenden (Farbe, Form, Linientyp, etc.)
  • Dann legen Sie sowohl die Kurvenarten als auch die Legends mit scale_xxx_manual manuell fest.
  • scale_xxx_manual können Ihnen einen Werte-Vektor zur Verfügung zu stellen, die länger als die tatsächliche Anzahl von Kurven sind, so ist es einfach, den Stil Vektor-Werte von den Größen der Art und Methode Faktoren
16

Ich hatte dieses Problem den anderen Tag. Der R-Kochbuch Abschnitt auf Legends erklärt:

Wenn Sie sowohl Farbe als auch Form verwenden, sie beide Skala Spezifikationen gegeben werden müssen. Sonst wird es zwei getrennte Legenden geben.

In Ihrem Fall benötigen Sie Spezifikationen für shape und linetype.

bearbeiten

Es war wichtig, die gleichen Daten zu haben, die Formen Farben und Linien zu schaffen, kombinierte ich Ihre Interaktion Phase direkt auf die Säule zu definieren. Anstelle von scale_linetype_discrete zum Erstellen der Legende habe ich scale_linetype_manual verwendet, um die Werte anzugeben, da sie standardmäßig vier verschiedene Werte annehmen.

Wenn Sie eine detaillierte Layout aller möglichen Formen und Linientypen haben möchten, this R Graphics site prüfen alle der Anzahl Kennungen zu sehen:

df.merged$int <- paste(df.merged$Type, df.merged$Method, sep=".") 

ggplot(df.merged, aes(x, y, colour = int, linetype=int, shape=int)) + 
    geom_line() + 
    geom_point() + 
    scale_colour_discrete("") + 
    scale_linetype_manual("", values=c(1,2,1,2)) + 
    scale_shape_manual("", values=c(17,17,16,16)) 

enter image description here

+1

Nun, das wäre das gleiche wie Diasbling-Legenden für Linientyp und Form, aber ich denke, das OP möchte 4 Legendensymbole mit unterschiedlicher Farbe/Linientyp/Form kombiniert in jedem – beetroot

+0

Nun, das ist fast das was ich suche: du hast eine Legende, wahr. Aber ich könnte das gleiche Ergebnis mit scale_shape (guide = FALSE) und scale_linetype (guide = FALSE) bekommen.Und mit deiner Lösung habe ich weder die durchgezogenen/gestrichelten Linien in der Legende, noch die Form. – Ben

+0

@beetroot Ich stimme zu – Ben

5

Der folgende Code führt zu der gewünschten Legende, Wenn ich Ihre Frage verstehe, aber ich bin mir nicht sicher, ob ich das Label-Problem verstehe, lassen Sie es mich wissen, wenn Sie nicht danach suchen.

p = ggplot(df.merged, aes(x, y, colour=interaction(Type, Method), 
          linetype=interaction(Type, Method), 
          shape=interaction(Type, Method))) + 
    geom_line() + 
    geom_point() 

p + scale_shape_manual(values=rep(16:17, 2)) + 
    scale_linetype_manual(values=rep(c(1,3),each=2)) 

enter image description here

+0

Dies ist eine Möglichkeit, es tatsächlich zu tun. Ich werde eine andere Lösung posten, die ich gefunden habe. IMHO, beide sind nicht sehr einfach und ich wünschte, es gäbe einen besseren Weg, mit diesem Fall umzugehen. – Ben

2

Man braucht nur an Namen berechnen beide führen gleich. Zum Beispiel:

g+ scale_linetype_manual(name="Guide1",values= c('solid', 'solid', 'dotdash'))+ 
    scale_colour_manual(name="Guide1", values = c("blue", "green","red")) 
+0

das funktioniert eigentlich ganz gut !!!!! –

Verwandte Themen