2016-10-17 1 views
0

Ich möchte Zeilen für separate Datenrahmen in derselben Grafik mit einer anderen Farbe für jeden Datenrahmen darstellen. Ich kann eine Legende mit fast dem gleichen Code und aes (color = "hard-coded-name") bekommen, aber ich kenne die Namen nicht im Voraus. Ich habe nicht genug RAM, um die Datenrahmen zu einem einzigen Datenrahmen zu verbinden. Ich habe ein Muster geschrieben, das die Zeichnung mit den farbigen Linien erzeugt. Wie füge ich eine Legende hinzu? Wie im Beispiel wissen Sie nicht im Voraus, wie viele Datenrahmen in der Liste sind (ldf) oder wie ihre Namen lauten.Fügen Sie eine fehlende Legende zu ggplot hinzu, wenn die Eingabedaten Listenfelder sind.

library('ggplot2') 

f30 <- function() { 
    ############################################################### 
    ##### Create a list with a random number of data frames ####### 
    ##### The names of the list elements are "random"  ####### 
    ############################################################### 
    f1 <- function(i) { 
     b <- sample(1:10, sample(8:10, 1)) 
     a <- sample(1:100, length(b)) 
     data.frame(Before = b, After = a) 
    } 
    ldf <- sapply(1:sample(2:8,1), f1, simplify = FALSE) 
    names(ldf) <- LETTERS[sample(1:length(LETTERS), length(ldf))] 

    palette <- c(
     "#000000", "#E69F00", "#56B4E9", "#009E73", 
     "#F0E442", "#0072B2", "#D55E00", "#CC79A7" 
    ) 

    ############################################################### 
    ##### Above this point we're just creating a sample ldf ####### 
    ############################################################### 

    ePlot <- new.env(parent = emptyenv()) 
    fColorsButNoLegend <- function(ix) { 
     df <- ldf[[ix]] 
     n <- names(ldf)[ix] 
     if (ix == 1) { 
      ePlot$p <- ggplot(df, aes(x = Before, y = After)) + 
       geom_line(colour = palette[ix]) 
     } else { 
      ePlot$p <- ePlot$p + 
       geom_line(
        colour = palette[ix], 
        aes(x = Before, y = After), 
        df 
       ) 
     } 
    } 
    sapply(1:length(ldf), fColorsButNoLegend) 

    #Add the title and display the plot 
    a <- paste(names(ldf), collapse = ', ') 
    ePlot$p <- ePlot$p + 
     ggtitle(paste("Before and After:", a)) 
    ePlot$p 
} 
+1

A lineplot muss nicht riesig data.frames. Wenn Ihre data.frames zu groß sind, um sie zu kombinieren, sind sie größer als für die Handlung erforderlich. Verwenden Sie Teilstichproben und kombinieren Sie diese. – Roland

+0

Das ist ein guter Punkt. Eigentlich, obwohl dies nur ein Teil einer größeren App ist, die Speicher beschränkt ist, will ich nicht unnötigen Druck hinzufügen. Ich bin sehr neu in ggplot. Wenn ich eine allgemeine Subroutine schreibe, die Liniplots verwendet, wäre es ratsam, Code hinzuzufügen, um die Größe zu überprüfen und Subsamples zu verwenden? An welcher Anzahl von x Punkten möchte ich das Subsampling einsetzen? –

+0

Das hängt von der Art Ihrer Daten ab. Wenn Sie einige glatte Daten haben, können Sie kleinere Teilproben verwenden; Wenn Sie sehr dynamische Daten mit vielen Peaks usw. haben, benötigen Sie möglicherweise größere Unterstichproben. – Roland

Antwort

1

die beiseite lassen setzen, für den Moment, die Frage, ob Sie jemals brauchen würden ein Liniendiagramm mit mehr Daten zu machen, als im RAM gehalten werden kann. Da die Listenelemente benannt sind, können Sie diese Namen verwenden, um eine Farblegende zu generieren, auch wenn Sie nicht im Voraus wissen, was diese Namen sein werden.

Zum Beispiel füge ich im folgenden Code den Namen des Listenelements als neue source Spalte in den Datenrahmen und dann diese source Spalte als Farbästhetik. Dann, kurz bevor die Handlung Druck, füge ich eine scale_colour_manual Anweisung, um die Linienfarben um sie auf Farbe gesetzt palette:

ePlot <- new.env(parent = emptyenv()) 
    fColorsButNoLegend <- function(ix) { 
    df <- ldf[[ix]] 

    # Add name of list element as a new column 
    df$source = names(ldf)[ix] 

    if (ix == 1) { 
     ePlot$p <- ggplot(df, aes(x = Before, y = After, colour=source)) + 
     geom_line() 
    } else { 
     ePlot$p <- ePlot$p + 
     geom_line(
      aes(x = Before, y = After, colour=source), 
      df 
     ) 
    } 
    } 
    sapply(1:length(ldf), fColorsButNoLegend) 

    #Add the title and display the plot 
    a <- paste(names(ldf), collapse = ', ') 
    ePlot$p <- ePlot$p + 
    ggtitle(paste("Before and After:", a)) + 
    scale_colour_manual(values=palette) 
    ePlot$p 

Hier ist Beispielausgabe der Funktion:

f30() 

enter image description here

+0

Vielen Dank, dass Sie sich die Zeit genommen haben, zu antworten. Bitte glaube nicht, dass ich nicht dankbar bin, obwohl ich eine alternative Lösung anbiete. –

0

Glücklicherweise habe ich gesehen, wie ein anderes Graph-Paket eine Alternative zu einer Legende bietet, die Bildschirmfläche spart und ich denke, es ist effizienter als das Hinzufügen einer Spalte oder das Duplizieren von Daten. Ich dachte, ich würde es hier zur Verfügung stellen, falls andere es nützlich finden könnten. Er bettet die Legende in den leeren Bereich des Diagramms ein. Sehen Sie sich die fAnnotate-Funktion an - die primitiv ist, aber genug, um den Keim einer Idee zu liefern.

enter image description here Bibliothek ('ggplot2')

f30 <- function() { 
    ############################################################### 
    ##### Create a list with a random number of data frames ####### 
    ##### The names of the list elements are "random"  ####### 
    ############################################################### 
    f1 <- function(i) { 
    b <- sample(1:10, sample(8:10, 1)) 
    a <- sample(1:100, length(b)) 
    data.frame(Before = b, After = a) 
    } 
    ldf <- sapply(1:sample(2:8,1), f1, simplify = FALSE) 
    names(ldf) <- LETTERS[sample(1:length(LETTERS), length(ldf))] 

    palette <- c(
    "#000000", "#E69F00", "#56B4E9", "#009E73", 
    "#F0E442", "#0072B2", "#D55E00", "#CC79A7" 
) 

    ############################################################### 
    ##### Above this point we're just creating a sample ldf ####### 
    ############################################################### 

    ePlot <- new.env(parent = emptyenv()) 
    ePlot$xMin <- Inf 
    ePlot$xMax <- -Inf 
    ePlot$yMin <- Inf 
    ePlot$yMax <- -Inf 
    fColorsButNoLegend <- function(ix) { 
    df <- ldf[[ix]] 

    #Compute the boundaries of x and y 
    ePlot$xMin <- min(ePlot$xMin, min(df$Before)) 
    ePlot$xMax <- max(ePlot$xMax, max(df$Before)) 
    ePlot$yMin <- min(ePlot$yMin, min(df$After)) 
    ePlot$yMax <- max(ePlot$yMax, max(df$After)) 

    n <- names(ldf)[ix] 
    if (ix == 1) { 
     ePlot$p <- ggplot(df, aes(x = Before, y = After)) + 
     geom_line(colour = palette[ix]) 
    } else { 
     ePlot$p <- ePlot$p + 
     geom_line(
      colour = palette[ix], 
      aes(x = Before, y = After), 
      df 
     ) 
    } 
    } 
    sapply(1:length(ldf), fColorsButNoLegend) 

    #Divide by length+1 to leave room on either side of the labels 
    xGap <- (ePlot$xMax - ePlot$xMin)/(length(ldf) + 1) 
    fAnnotate <- function(ix) { 
    x <- ePlot$xMin + (ix * xGap) 
    lbl <- paste('---', names(ldf)[ix]) 
    b <- palette[ix] 
    ePlot$p <- ePlot$p + 
     annotate("text", x = x, y = -Inf, vjust = -1, label = lbl, colour = b) 
    } 
    sapply(1:length(ldf), fAnnotate) 

    #Add the title and display the plot 
    allNames <- paste(names(ldf), collapse = ', ') 
    ePlot$p <- ePlot$p + 
    ggtitle(paste("Before and After:", allNames)) 
    ePlot$p 
} 
Verwandte Themen