2015-08-03 18 views
8

Ho alcuni dati mensili e voglio aggiungere una colonna al mio frame di dati che associa il valore più piccolo nella prima colonna al valore più grande nella prima colonna. Il secondo valore più piccolo nella prima colonna per il secondo valore più grande nella prima colonna, ect ...Aggiunta di colonne classificate al frame di dati

Ecco alcuni dati di esempio

x1<-c(100,151,109,59,161,104,170,101) 
dat<-data.frame(x1) 
rownames(dat)<-c('Apr','May', 'Jun','Jul', 'Aug', 'Sep', 'Oct', 'Nov') 

    x1 
Apr 100 
May 151 
Jun 109 
Jul 59 
Aug 161 
Sep 104 
Oct 170 
Nov 101 

io sto cercando di ottenere i miei dati a guardare come questo

 x1 x2 
Apr 100 161 
May 151 101 
Jun 109 104 
Jul 59 170 
Aug 161 100 
Sep 104 109 
Oct 170 59 
Nov 101 151 

Sto andando in circolo con rango, ordine e ordine. Qualsiasi aiuto sarebbe apprezzato.

risposta

6

E 'abbastanza semplice se si crea un oggetto temporaneo che ha il salire e scendere i valori appaiati:

> temp <- data.frame(asc =x1[order(x1)],desc=x1[rev(order(x1))]) 
> dat$x2 <- temp$desc[ match(dat$x1, temp$asc) ] 
> dat 
    x1 x2 
Apr 100 161 
May 151 101 
Jun 109 104 
Jul 59 170 
Aug 161 100 
Sep 104 109 
Oct 170 59 
Nov 101 151 

La funzioneè progettata per costruire valori di indicizzazione integer che vengono utilizzati come argomenti su "[". È la funzione fondamentale all'interno di merge.

4

Facendo uso della base di R month.abb

df = dat[order(dat$x1),, drop = FALSE] 
df$x2 = sort(x1,decreasing = T) 
df[match(month.abb, rownames(df), nomatch = 0),] 

#  x1 x2 
#Apr 100 161 
#May 151 101 
#Jun 109 104 
#Jul 59 170 
#Aug 161 100 
#Sep 104 109 
#Oct 170 59 
#Nov 101 151 

Utilizzando data.table semplicemente

library(data.table) 
df = setDF(setDT(dat, keep.rownames=T)[order(x1), x2 := sort(x1, decreasing = T)]) 
rownames(df) = df$rn; df[,1] = NULL 

#  x1 x2 
#Apr 100 161 
#May 151 101 
#Jun 109 104 
#Jul 59 170 
#Aug 161 100 
#Sep 104 109 
#Oct 170 59 
#Nov 101 151 
4

un'idea simile come @BondedDust:

library(dplyr) 
dat %>% mutate(x2 = x1[match(row_number(desc(x1)), row_number(x1))]) 

che dà:

# x1 x2 
#1 100 161 
#2 151 101 
#3 109 104 
#4 59 170 
#5 161 100 
#6 104 109 
#7 170 59 
#8 101 151 
3

Approccio in data.table:

library(data.table) 
setDT(dat,keep.rownames=T)[order(x1),x2:=rev(x1)] 
    rn x1 x2 
1: Jul 59 170 
2: Apr 100 161 
3: Nov 101 151 
4: Sep 104 109 
5: Jun 109 104 
6: May 151 101 
7: Aug 161 100 
8: Oct 170 59 

Se si vuole finire con le righe in ordine, Penso che il modo più semplice sia usare month.abb come livelli di rn a s un fattore:

setDT(dat,keep.rownames=T)[order(x1),x2:=rev(x1) 
          ][order(factor(rn,levels=month.abb))] 
    rn x1 x2 
1: Apr 100 161 
2: May 151 101 
3: Jun 109 104 
4: Jul 59 170 
5: Aug 161 100 
6: Sep 104 109 
7: Oct 170 59 
8: Nov 101 151 

potrebbe anche usare order(match(rn,month.abb)) invece, se questo ti si addice; se avete intenzione di essere ri-ordinamento molto per mese, può essere utile per definire rn come un fattore in modo da non dovete fare il cane e pony spettacolo match o factor ripetutamente: dat[,rn:=factor(rn,levels=month.abb)][order(rn)]

+2

L'ordine originale dovrebbe essere recuperato alla fine, no? – Frank

+0

Non necessariamente, ma sto aggiungendo una modifica per farlo se è così. – MichaelChirico

+0

@VeerendraGadekar aggiunto bonus: non serve più la versione di sviluppo di 'data.table' per usare il mio codice (credo ...) – MichaelChirico

Problemi correlati