2009-09-08 15 views
10

Ho un frame di dati con diverse colonne, una delle quali è un fattore chiamato "sito". Come posso dividere il frame di dati in blocchi di righe ciascuno con un valore univoco di "sito" e quindi elaborare ogni blocco con una funzione? I dati appaiono così:Come dividere un frame di dati per righe e quindi elaborare i blocchi?

site year peak 
ALBEN 5 101529.6 
ALBEN 10 117483.4 
ALBEN 20 132960.9 
ALBEN 50 153251.2 
ALBEN 100 168647.8 
ALBEN 200 184153.6 
ALBEN 500 204866.5 
ALDER 5 6561.3 
ALDER 10 7897.1 
ALDER 20 9208.1 
ALDER 50 10949.3 
ALDER 100 12287.6 
ALDER 200 13650.2 
ALDER 500 15493.6 
AMERI 5 43656.5 
AMERI 10 51475.3 
AMERI 20 58854.4 
AMERI 50 68233.3 
AMERI 100 75135.9 
AMERI 200 81908.3 

e voglio creare un terreno di year vs peak per ogni sito.

risposta

12

Un'altra scelta è utilizzare la funzione ddply dalla libreria ggplot2. Ma si parla si principalmente vuole fare un appezzamento di picco rispetto l'anno, così si potrebbe anche semplicemente usare qplot:

A <- read.table("example.txt",header=TRUE) 
library(ggplot2) 
qplot(peak,year,data=A,colour=site,geom="line",group=site) 
ggsave("peak-year-comparison.png") 

alt text http://i32.tinypic.com/16nuza.png

D'altra parte, mi piace la soluzione di David Smith che permette al applicazione della funzione da eseguire su più processori.

14

È possibile utilizzare isplit (dal pacchetto "iteratori") per creare un oggetto iteratore che loop sopra i blocchi definiti dalla colonna site:

require(iterators) 
site.data <- read.table("isplit-data.txt",header=T) 
sites <- isplit(site.data,site.data$site) 

quindi è possibile utilizzare foreach (dal "foreach" pacchetto) per creare una trama all'interno di ogni blocco:

require(foreach) 
foreach(site=sites) %dopar% { 
pdf(paste(site$key[[1]],".pdf",sep="")) 
plot(site$value$year,site$value$peak,main=site$key[[1]]) 
dev.off() 
} 

Come bonus, se si dispone di una macchina multiprocessore e chiamare registerDoMC() prima (dal pacchetto "domc"), i loop verrà eseguito in parallelo, spe sistemare le cose. Maggiori dettagli in questo post del blog Rivoluzioni: Block-processing a data frame with isplit

4

Ci sono due pratiche funzioni incorporate per affrontare questo tipo di situazioni. ? aggregato e? da. In questo caso, perché si vuole una trama e non stanno tornando uno scalare, l'utilizzo da parte()

data <- read.table("example.txt",header=TRUE)

by(data[, c('year', 'peak')], data$site, plot)

L'uscita dice NULL perché è quello che restituisce trama. Potresti voler impostare il dispositivo grafico in pdf per catturare tutto l'output.

6

Ecco cosa vorrei fare, anche se sembra che voi ragazzi lo abbiate gestito dalle funzioni della libreria.

for(i in 1:length(unique(data$site))){ 
    constrainedData = data[data$site==data$site[i]]; 
    doSomething(constrainedData); 
} 

Questo tipo di codice è più diretto e potrebbe essere meno efficiente, ma preferisco essere in grado di leggere quello che sta facendo di imparare qualche nuova funzione di libreria per la stessa cosa. rende anche questo più flessibile, ma in tutta onestà questo è proprio il modo in cui l'ho capito come un novizio.

+1

Karl, sono d'accordo che questo è leggibile. Ma il codice da tracciare ('doSomething') sarebbe molto meno. Buona soluzione per un problema diverso imho. – isomorphismes

10

Mi sembra di ricordare che il semplice vecchio split() ha un metodo per data.frames, in modo che split(data,data$site) generi un elenco di blocchi. È quindi possibile operare su questo elenco utilizzando sapply/lapply/for.

split() è anche bello a causa di unsplit(), che creerà un vettore della stessa lunghezza dei dati originali e nell'ordine corretto.

2

E 'anche molto facile da generare i diagrammi con il pacchetto reticolo:

library(lattice) 
xyplot(year~peak | site, data) 
0

è possibile utilizzare la funzione di split Se avete aperto i vostri dati come:

data <- read.table('your_data.txt', header=T) 
blocks <- split(data, data$site) 

Dopo di che, i blocchi contiene i dati di ogni blocco, che è possibile accedere come altri data.frame:

plot(blocks$ALBEN$year, blocks$ALBEN$peak) 

E così via per ogni trama.