2010-12-02 9 views
23

Wie kann ich einen sehr großen Datensatz in R plotten?Plotten sehr großer Datensätze in R

Ich würde gerne einen Boxplot oder Violinplot oder ähnliches verwenden. Alle Daten können nicht in den Speicher passen. Kann ich die Zusammenfassungen, die zur Erstellung dieser Diagramme benötigt werden, schrittweise einlesen und berechnen? Wenn das so ist, wie?

+1

Was genau bedeutet "sehr groß" in Ihrem Fall? – radek

+3

@radek: "Alle Daten können nicht in den Speicher passen" scheint eine gute Annäherung an "viel zu groß für R" zu sein. Ob es 2Gb oder 20Gb ist spielt keine Rolle mehr, oder? –

+1

@Joris Es sei denn OP hat memory.limit zu klein oder viele unnötige Spalten oder etwas anderes. Diese Information könnte relevant sein. – Marek

Antwort

10

In Ergänzung zu meinem Kommentar zu Dmitri answer, um eine Funktion quantiles zu berechnen mit ff Big Data Handling-Paket:

ffquantile<-function(ffv,qs=c(0,0.25,0.5,0.75,1),...){ 
stopifnot(all(qs<=1 & qs>=0)) 
ffsort(ffv,...)->ffvs 
j<-(qs*(length(ffv)-1))+1 
jf<-floor(j);ceiling(j)->jc 
rowSums(matrix(ffvs[c(jf,jc)],length(qs),2))/2 
} 

Dies ist ein exakter Algorithmus, so dass es das Sortieren verwendet - und damit kann nehmen Sie sich viel Zeit.

+2

sieht aus wie Sie versuchen, eine Art von <-...-> Symmetrie in Ihrem Code zu erreichen;) – VitoshKa

+0

Vielen Dank, ich werde dies eine Chance geben.Ich vermute, dass es einige Zeit dauern wird, aber dafür sind Server da;) In der Zwischenzeit werde ich probieren, wie Joris Meys vorgeschlagen hatte –

3

Alles, was Sie für einen Boxplot benötigen, sind die Quantile, die "Whisker" -Extreme und die Ausreißer (falls angezeigt), die alle leicht vorberechnet werden können. Schauen Sie sich die boxplot.stats Funktion an.

+3

Aber es ist nicht möglich, sie genau zu berechnen, ohne alle Daten in den Speicher zu laden. – hadley

+3

@hadley Nein, 'ff' Paket erlaubt Ihnen, wie üblich, aber auf Daten, die teilweise auf der Festplatte gespeichert sind, Quantile zu zählen. – mbq

+0

@mbq: Aus Neugier: Welche Funktion in ff würde das tun? Ich sah ff vor allem als Schnittstelle, um große Daten effizient zu speichern, meist in Kombination mit Genomik. Aber ich kann völlig falsch liegen. –

2

Sie könnten Diagramme aus überschaubaren Stichproben Ihrer Daten erstellen. Z.B. Wenn Sie nur 10% zufällig ausgewählte Zeilen verwenden, sollte sich das Boxplot für dieses Beispiel nicht vom Boxplot für alle Daten unterscheiden.

Wenn Ihre Daten in einer Datenbank sind, können Sie ein zufälliges Flag erstellen (da ich weiß, dass fast jede Datenbank-Engine irgendeine Art von Zufallszahlengenerator hat).

Zweitens ist, wie groß ist Ihr Datensatz? Für Boxplot benötigen Sie zwei Spalten: Wertvariable und Gruppenvariable. Dieses Beispiel:

N <- 1e6 
x <- rnorm(N) 
b <- sapply(1:100, function(i) paste(sample(letters,40,TRUE),collapse="")) 
g <- factor(sample(b,N,TRUE)) 
boxplot(x~g) 

benötigt 100 MB RAM. Wenn N=1e7 dann verwendet es < 1 GB RAM (die noch zu modernen Maschine verwaltbar ist).

2

Dies ist ein interessantes Problem.

Boxplots erfordern Quantile. Das Berechnen von Quantilen in sehr großen Datensätzen ist schwierig.

Die einfachste Lösung, die in Ihrem Fall funktionieren kann oder nicht, besteht darin, die Daten zuerst zu verkleinern und Plots der Probe zu erstellen. Mit anderen Worten, lesen Sie eine Reihe von Datensätzen gleichzeitig und behalten Sie eine Teilmenge davon im Speicher (entweder deterministisch oder zufällig). Am Ende erzeugen Sie Diagramme basierend auf den Daten, die im Speicher gehalten wurden. Ob dies realisierbar ist, hängt wiederum stark von den Eigenschaften Ihrer Daten ab.

Alternativ gibt es Algorithmen, die Quantile in einer "Online" -Methode ökonomisch und näherungsweise berechnen können, was bedeutet, dass sie jeweils mit einer Beobachtung dargestellt werden und jede Beobachtung genau einmal gezeigt wird. Obwohl ich nur begrenzte Erfahrung mit solchen Algorithmen habe, habe ich keine leicht verfügbaren R-Implementierungen gesehen.

Das folgende Papier gibt einen kurzen Überblick über einige relevante Algorithmen: Quantiles on Streams.

8

Problem ist, dass Sie nicht alle Daten in den Speicher laden können. Sie können also, wie bereits von @Marek angezeigt, Stichproben der Daten durchführen. Auf solch riesigen Datensätzen erhalten Sie im Wesentlichen die gleichen Ergebnisse, selbst wenn Sie nur 1% der Daten verwenden. Für den Violin-Plot erhalten Sie eine ordentliche Schätzung der Dichte. Eine progressive Berechnung von Quantilen ist unmöglich, aber dies sollte eine sehr gute Annäherung ergeben. Es ist im Wesentlichen das gleiche wie die "randomisierte Methode", die im Link @aix beschrieben wurde.

Wenn Sie das Datum nicht außerhalb von R subset- zen können, kann dies über Verbindungen in Kombination mit sample() geschehen. Folgende Funktion verwende ich, um Daten von einem Datenrahmen im Textformat zu erfassen, wenn es zu groß wird. Wenn Sie ein wenig mit der Verbindung spielen, könnten Sie dies leicht in eine socketConnection konvertieren, um sie von einem Server oder einer Datenbank zu lesen. Stellen Sie sicher, dass Sie die Verbindung im richtigen Modus öffnen.

Gut, nimm ein einfaches.CSV-Datei, dann Proben folgende Funktion ein Bruchteil p der Daten:

sample.df <- function(f,n=10000,split=",",p=0.1){ 
    con <- file(f,open="rt",) 
    on.exit(close(con,type="rt")) 
    y <- data.frame() 
    #read header 
    x <- character(0) 
    while(length(x)==0){ 
     x <- strsplit(readLines(con,n=1),split)[[1]] 
    } 
    Names <- x 
    #read and process data 
    repeat{ 
     x <- tryCatch(read.table(con,nrows=n,sep=split),error = function(e) NULL) 
     if(is.null(x)) {break} 
     names(x) <- Names 
     nn <- nrow(x) 
     id <- sample(1:nn,round(nn*p)) 
     y <- rbind(y,x[id,]) 
    } 
    rownames(y) <- NULL 
    return(y) 
} 

Ein Beispiel für die Nutzung:

#Make a file 
Df <- data.frame(
    X1=1:10000, 
    X2=1:10000, 
    X3=rep(letters[1:10],1000) 
) 
write.csv(Df,file="test.txt",row.names=F,quote=F) 

# n is number of lines to be read at once, p is the fraction to sample 
DF2 <- sample.df("test.txt",n=1000,p=0.2) 
str(DF2) 

#clean up 
unlink("test.txt") 
+0

Ich hatte einen Algorithmus implementiert, aber dieser war so unglaublich langsam, wenn er an einem realen Datensatz versucht wurde, löschte ich ihn erneut. Es bringt nichts, und in jedem Fall ist das "blockierte" Sampling, wie es die Funktion sample.df tut, bei weitem der beste Ansatz, wenn wir über Sampling sprechen, ohne die Verteilung zu verzerren. –

+0

Das war am Ende sehr nützlich. Vielen Dank für Ihre Hilfe Joris Meys. –

4

Sie sollten am RSQLite, SQLiteDF, RODBC schauen auch, und biglm Pakete. Für große Datensätze kann es nützlich sein, die Daten in einer Datenbank zu speichern und nur Stücke in R zu ziehen. Die Datenbanken können auch für Sie sortieren und dann ist die Berechnung von Quantilen an sortierten Daten viel einfacher (dann verwenden Sie einfach die Quantile, um die Diagramme zu erstellen) .

Es gibt auch das Hexbin-Paket (Bioconductor) für Scatterplot-Äquivalente mit sehr großen Datensätzen (wahrscheinlich noch eine Probe der Daten verwenden möchten, aber mit einem großen Beispiel arbeitet).