2012-10-23 10 views
5

Sto provando a scrivere un programma che richiede un grande frame di dati e sostituisce ogni colonna di valori per la frequenza cumulativa di quei valori (ordinati in ordine crescente). Ad esempio, se la colonna di valori sono: 5, 8, 3, 5, 4, 3, 8, 5, 5, 1. Poi le frequenze relative e cumulativi sono:sostituzione efficiente del frame di dati con frequenza cumulativa

  • 1: rel_freq = 0.1, cum_freq = 0.1
  • 3: rel_freq = 0.2, cum_freq = 0.3
  • 4: rel_freq = 0.1, cum_freq = 0.4
  • 5: rel_freq = 0.4, cum_freq = 0.8
  • 8: rel_freq = 0.2, cum_freq = 1.0

Quindi il co originale lumn diventa: 0,8, 1,0, 0,3, 0,8, 0,4, 0,3, 1,0, 0,8, 0,8, 0,1

Il codice seguente esegue questa operazione correttamente, ma si adatta in modo errato probabilmente a causa del ciclo nidificato. Qualche idea su come eseguire questa attività in modo più efficiente?

mydata = read.table(.....) 

totalcols = ncol(mydata) 
totalrows = nrow(mydata) 

for (i in 1:totalcols) { 
    freqtable = data.frame(table(mydata[,i])/totalrows) # create freq table 
    freqtable$CumSum = cumsum(freqtable$Freq) # calc cumulative freq 

    hashtable = new.env(hash=TRUE) 
    nrows = nrow(freqtable) 

    # store cum freq in hash 
    for (x in 1:nrows) { 
     dummy = toString(freqtable$Var1[x]) 
     hashtable[[dummy]] = freqtable$CumSum[x] 
    } 

    # replace original data with cum freq 
    for (j in 1:totalrows) { 
     dummy = toString(mydata[j,i]) 
     mydata[j,i] = hashtable[[dummy]] 
    } 
} 
+0

può noi una darvi [esempio riproducibile] (http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-exa mple)? –

risposta

2

Questo gestisce una singola colonna senza la for -loop:

R> x <- c(5, 8, 3, 5, 4, 3, 8, 5, 5, 1) 
R> y <- cumsum(table(x)/length(x)) 
R> y[as.character(x)] 
    5 8 3 5 4 3 8 5 5 1 
0.8 1.0 0.3 0.8 0.4 0.3 1.0 0.8 0.8 0.1 
+0

Ottima risposta! Il mio programma scala molto meglio usando questo codice. Grazie! – user1769120

1

Ecco un modo. Utilizzando un frame di dati con due variabili ciascuna contenenti i dati esemplificativi

d <- data.frame(var1 = c(5, 8, 3, 5, 4, 3, 8, 5, 5, 1), 
       var2 = c(5, 8, 3, 5, 4, 3, 8, 5, 5, 1)) 

uso una semplice funzione di

  1. generare il cumsum() delle relative proporzioni indicate da table(x)/length(x), quindi
  2. match() le osservazioni in un variabile con i nomi della tabella delle somme cumulative, quindi
  3. utilizzare le corrispondenze id per selezionare dalla tabella delle somme cumulative (e non nominare)

Tali un funzioni è:

f <- function(x) { 
    tab <- cumsum(table(x)/length(x)) 
    ind <- match(x, as.numeric(names(tab))) 
    unname(tab[ind]) 
} 

In pratica usiamo lapply() e costringere ad un frame di dati:

out <- data.frame(lapply(d, f)) 
out 

che dà:

R> out 
    var1 var2 
1 0.8 0.8 
2 1.0 1.0 
3 0.3 0.3 
4 0.8 0.8 
5 0.4 0.4 
6 0.3 0.3 
7 1.0 1.0 
8 0.8 0.8 
9 0.8 0.8 
10 0.1 0.1 
+0

Grazie, farò un tentativo. – user1769120

Problemi correlati