2012-11-18 15 views
18

Sto tentando di popolare un frame di dati da un ciclo for in R. I nomi delle colonne sono generati dinamicamente all'interno del ciclo e viene utilizzato il valore di alcune variabili del ciclo come valori durante la compilazione del frame di dati. Ad esempio, il nome della colonna corrente potrebbe essere il nome di una variabile come stringa nel ciclo e la colonna può assumere il valore dell'attuale iteratore come valore nel frame di dati.Compilazione di un frame di dati in R in un loop

Ho cercato di creare una cornice di dati vuoto al di fuori del ciclo, come questo

d = data.frame() 

ma non posso davvero fare qualsiasi cosa con esso, il momento cerco di popolarla, mi imbatto in un errore

d[1] = c(1,2) 
Error in `[<-.data.frame`(`*tmp*`, 1, value = c(1, 2)) : 
    replacement has 2 rows, data has 0 

Quale potrebbe essere un buon modo per ottenere quello che sto cercando di fare. Per favore fatemi sapere se non ero chiaro.

+1

popolare un 'list' invece di un' data.frame' e di trasformarlo in un 'data.frame' dopo il ciclo. – Roland

+2

Grazie Roland, sono un n00b, puoi per favore elaborare di più? Come dichiarare la lista e come convertirla? –

risposta

28

Si potrebbe fare così:

iterations = 10 
variables = 2 

output <- matrix(ncol=variables, nrow=iterations) 

for(i in 1:iterations){ 
    output[i,] <- runif(2) 

} 

output 

e poi trasformarlo in un data.frame

output <- data.frame(output) 
class(output) 

ciò che fa:

  1. crea una matrice con righe e colonne secondo alla crescita prevista
  2. insert 2 ran numeri dom nella matrice
  3. convertire questo in un dataframe dopo il ciclo è terminato.
35

Spesso è preferibile evitare i loop e utilizzare le funzioni vettoriali. Se questo non è possibile, ci sono due approcci:

  1. Preallocare tuo data.frame. Questo non è consigliato perché l'indicizzazione è lenta per data.frames.
  2. Utilizzare un'altra struttura dati nel loop e trasformarsi in un data.frame in seguito. A list è molto utile qui.

esempio per illustrare l'approccio generale:

mylist <- list() #create an empty list 

for (i in 1:5) { 
    vec <- numeric(5) #preallocate a numeric vector 
    for (j in 1:5) { #fill the vector 
    vec[j] <- i^j 
    } 
    mylist[[i]] <- veC#put all vectors in the list 
} 
df <- do.call("rbind",mylist) #combine all vectors into a matrix 

In questo esempio non è necessario utilizzare un list, si potrebbe preallocare un matrix. Tuttavia, se non si conosce il numero di iterazioni necessario per il ciclo, è necessario utilizzare uno list.

Infine ecco un vettorializzare alternativa all'esempio ciclo:

outer(1:5,1:5,function(i,j) i^j) 

Come si vede è più semplice e anche più efficiente.

+4

Puoi semplificare la tua versione vettoriale ancora di più: 'outer (1: 5,1: 5,"^")' – thelatemail

0

Ho avuto un caso in cui mi è stato bisogno di usare un frame di dati all'interno di una funzione per ciclo. In questo caso, è stata la "efficiente", tuttavia, tenere a mente che il database era piccolo e le iterazioni del ciclo erano molto semplici.Ma forse il codice potrebbe essere utile per qualcuno con condizioni simili.

Il ciclo for scopo era quello di utilizzare la funzione di estratto di raster lungo cinque sedi (vale a dire 5 Tokio, New York, Sau Paulo, città Seul & Messico) e ogni posizione avuto le loro rispettive griglie raster. Avevo un database di punti spaziali con più di 1000 osservazioni allocate all'interno delle 5 diverse posizioni e avevo bisogno di estrarre informazioni da 10 diverse griglie raster (due griglie per posizione). Inoltre, per l'analisi successiva, non avevo solo bisogno dei valori raster ma anche dell'ID univoco per ogni osservazione.

Dopo aver preparato i dati spaziali, che comprendeva i seguenti compiti:

  1. punti importazione shapefile con la readOGR funzione (pacchetto rgdap)
  2. file Importa raster con la funzione raster (pacchetto raster
  3. Stack di griglie dalla stessa posizione in un unico file, con la funzione stack (pacchetto raster)

Qui il codice ciclo con l'uso di un frame di dati :

1. aggiuntivi impilati raster per sede in un elenco

raslist <- list(LOC1,LOC2,LOC3,LOC4,LOC5) 

2. Creare un vuoto dataframe, questo sarà il file di output

TB <- data.frame(VAR1=double(),VAR2=double(),ID=character()) 

3. L'impostazione della funzione loop

L1 <- seq(1,5,1) # the location ID is a numeric variable with values from 1 to 5 

for (i in 1:length(L1)) { 
    dat=subset(points,LOCATION==i) # select corresponding points for location [i] 
    t=data.frame(extract(raslist[[i]],dat),dat$ID) # run extract function with points & raster stack for location [i] 
    names(t)=c("VAR1","VAR2","ID") 
    TB=rbind(TB,t) 
} 
Problemi correlati