2013-05-09 4 views
6

Breve: come posso aggiungere m righe al mio frame dati m X n, dove ogni nuova riga viene inserita dopo ogni riga esistente? In pratica copierò la riga esistente, ma apporterò una modifica a una variabile.Come posso aggiungere righe a un frame di dati R ogni altra riga?

Ulteriori dettagli: in riferimento a another question, penso di poter fare ciò che voglio con la funzione segment3d di rgl. Ho un insieme di punti x, y, z, ma questi sono solo un punto finale di un insieme di segmenti di linea. L'altro punto finale è di molti metri di distanza nella dimensione Z, dato come una quarta variabile: X, Y, Z, Z_Length; nella mia terminologia è est, nord, altezza, lunghezza.

In base ai documenti legali, "I punti sono presi in coppia per segmenti3d". Quindi, penso di aver bisogno di modificare il mio frame di dati per avere entrate extra ogni seconda riga con una variabile Z alterata (sottraendo Z_Length da Z). Visivamente, ha bisogno di andare da questo:

+-------+---------+----------+-----------+---------+ 
| Label | easting | northing | elevation | length | 
+-------+---------+----------+-----------+---------+ 
| 47063 | 554952 | 5804714 | 32.68  | 619.25 | 
| 47311 | 492126 | 5730703 | 10.40  | 1773.00 | 
+-------+---------+----------+-----------+---------+ 

a questo:

+-------+---------+----------+-----------+---------+ 
| Label | easting | northing | elevation | length | 
+-------+---------+----------+-----------+---------+ 
| 47063 | 554952 | 5804714 | 32.68  | 619.25 | 
| 47063 | 554952 | 5804714 | -586.57 | 619.25 | 
| 47311 | 492126 | 5730703 | 10.40  | 1773.00 | 
| 47311 | 492126 | 5730703 | -1762.26 | 1773.00 | 
+-------+---------+----------+-----------+---------+ 

un campione di dati la questione legata è disponibile.

risposta

8

I suoi dati di esempio:

orig.df <- read.table(text = " 
Label easting northing elevation length 
47063 554952 5804714 32.68 619.25 
47311 492126 5730703 10.40 1773.00", header = TRUE) 

Creare i dati da inserire:

insert.df <- transform(orig.df, elevation = elevation - length) 

aggiungerlo al tuo dati originali:

out.df <- rbind(orig.df, insert.df) 

riordinare le righe:

n <- nrow(orig.df) 
out.df[kronecker(1:n, c(0, n), "+"), ] 
# Label easting northing elevation length 
# 1 47063 554952 5804714  32.68 619.25 
# 3 47063 554952 5804714 -586.57 619.25 
# 2 47311 492126 5730703  10.40 1773.00 
# 4 47311 492126 5730703 -1762.60 1773.00 
+0

Ho pensato che avrei dovuto usare una specie di tipo nella mia soluzione, ma kronecker non è quello che mi aspettavo ... puoi spiegare come fa quello che fa? –

+2

Vedere cosa 'kronecker (1: 5, c (0,5)," + ")' ti dà. Per ogni elemento nel primo vettore, aggiunge ('FUN =" + "') tutti gli elementi nel secondo vettore, quindi ottieni: '1 + 0, 1 + 5, 2 + 0, 2 + 5, ecc. '. Ci sono certamente altri modi per ottenere quel vettore di indici, ma trovo questo interessante. – flodel

+2

È selvaggio, lo adoro. Il tuo cervello funziona in modo meraviglioso. –

2

Ecco un possibile approccio se ho capito quello che stai facendo:

dat <- head(CO2, 10) # fake data set 

L1 <- lapply(1:nrow(dat), function(i) { 
    dat2x <- dat[i, ] 
    dat2x[4] <- dat[i, 4] - dat[i, 5] 
    rbind(dat[i, ], dat2x) 
}) 
do.call(rbind, L1) 

EDIT: totalmente lavorando fuori eccellente risposta di e4e5f4:

new <- dat[rep(1:nrow(dat),1,each=2),] 
new[c(F, T),4] <- dat[4] - dat[5] 

Entrambi sono equivalenti ma suppongo l'alter è molto più veloce.

+0

(+1) per fornire una risposta completa.Non ho notato la modifica necessaria nella colonna 4! – Nishanth

+1

Sì, mi sono perso anche al mio primo giro. –

0

È possibile creare una nuova matrice con il doppio delle righe, riportare i vecchi elementi del frame di dati nelle posizioni appropriate della nuova matrice e lasciare gli spazi. Eseguire i calcoli in elevazione, creando una nuova matrice, quindi inserire la matrice di elevazione corretta nella nuova matrice più grande. Quindi riconvertire la matrice in un frame di dati.

test <- matrix(1:9, ncol=3) 
ind <- (1:nrow(test)*2 - 1 # - 1 b/c you want to insert rows after, not before, existing rows 
test_new <- matrix(rep(NA, (nrow(test)*2*ncol(test))), ncol=ncol(test)) 
test_new[ind,] <- test 

test_elev <- test #create a new matrix that will have adjusted elevations 
test_elev[,2] <- test[,2] - test[,3] #e.g., test[,2] is the elevation column, and test[,3] is the length column 
test_new[ind+1,] <- test_elev #then put the new elevations into the new matrix 

#if you need it to be a data.frame() again, you can use `as.data.frame(test_new)` 
5

io non sono sicuro di come rgl entra in gioco qui, ma se si desidera solo per creare una nuova data.frame con valori ripetuti, provo:

df[rep(1:nrow(df),1,each=2),] 
+0

rgl perché la prima bozza di domanda era più incentrata sull'aspetto di segmenti3d. La bozza finale lo ha cambiato per essere più di una query sulla cornice dati. Grazie per la risposta. –

+0

Cosa sta facendo l'1 nel rep (..., 1, ...)? Sembra funzionare bene senza di esso? – Xizam

2

modificato da "e4e5f4 di" risposta

inserire righe vuote Betweens righe

# sample matrix of df 
    old <-matrix(1:9, ncol=3) 

    # double all rows 
    new <- old[rep(1:nrow(old),1,each=2),] 

    # replace all duplicates with blank cells 
    new[c(seq(2, dim(new)[1], by=2)), ] <- "" 

    old # original 
    new # all ok ;)