2015-07-31 16 views
5

Ho un data.frame di 130.209 righe.come faccio a dividere un dataframe per fila in blocchi di n, applicare una funzione e combinare?

> head(dt) 

       mLow1 mHigh1 mLow2 mHigh2 meanLow meanHigh  fc  mean 
    A_00001 37.00 12.75 99.25 78.50 68.125 45.625 1.4931507 56.8750 
    A_00002 31.00 21.50 84.75 53.00 57.875 37.250 1.5536913 47.5625 
    A_00003 72.50 26.50 81.75 74.75 77.125 50.625 1.5234568 63.8750 

voglio dividere il data.frame in 12, applicare la funzione scale sulla colonna fc e poi combinarlo. Non c'è alcuna variabile di raggruppamento qui, altrimenti avrei usato ddply. Inoltre, poiché 130.209 non è perfettamente divisibile per 12, lo data.frames risultante sarà sbilanciato, vale a dire 11 data.frame s avrà 10.851 file e l'ultimo avrà 10.848 righe, ma va bene.

Quindi, come faccio a dividere uno data.frame per riga in blocchi di n (in questo caso 12), applicare una funzione e combinarli insieme? Qualsiasi aiuto sarebbe molto apprezzato.

Aggiornamento: Utilizzando le due soluzioni migliori, ottengo risultati diversi: Utilizzando la soluzione di @ Ben Bolker,

mLow1 mHigh1 mLow2 mHigh2   UID  gene_id meanLow meanHigh mean   fc 
    1.5 3.25  1 1.25 MGLibB_00021 0610010K14Rik 1.25  2.25 1.75 -0.5231249 
    1.5 3.25  1 1.25 MGLibA_00034 0610037L13Rik 1.25  2.25 1.75 -0.5231249 
    1.5 3.25  1 1.25 MGLibB_00058 1100001G20Rik 1.25  2.25 1.75 -0.5231249 
    1.5 3.25  1 1.25 MGLibA_00061 1110001A16Rik 1.25  2.25 1.75 -0.5231249 
    1.5 3.25  1 1.25 MGLibA_00104 1110034G24Rik 1.25  2.25 1.75 -0.5231249 
    1.5 3.25  1 1.25 MGLibA_00110 1110038F14Rik 1.25  2.25 1.75 -0.5231249 

Utilizzando @ risposta di MichaelChirico:

mLow1 mHigh1 mLow2 mHigh2   UID  gene_id meanLow meanHigh mean  fc fc_scaled 
    1.5 3.25  1 1.25 MGLibB_00021 0610010K14Rik 1.25  2.25 1.75 0.5555556 -0.5089608 
    1.5 3.25  1 1.25 MGLibA_00034 0610037L13Rik 1.25  2.25 1.75 0.5555556 -0.5089608 
    1.5 3.25  1 1.25 MGLibB_00058 1100001G20Rik 1.25  2.25 1.75 0.5555556 -0.5089608 
    1.5 3.25  1 1.25 MGLibA_00061 1110001A16Rik 1.25  2.25 1.75 0.5555556 -0.5089608 
    1.5 3.25  1 1.25 MGLibA_00104 1110034G24Rik 1.25  2.25 1.75 0.5555556 -0.5089608 
    1.5 3.25  1 1.25 MGLibA_00110 1110038F14Rik 1.25  2.25 1.75 0.5555556 -0.5089608 
+0

questo numero di riga non è grande. Perché ti piacerebbe operare in scala separatamente e combinare i risultati invece di scalare direttamente la colonna fc ?? –

+0

Voglio controllare il fc (fold change) per l'abbondanza media (media). I dati sono ordinati per media nel mio attuale dataframe. Voglio calcolare separatamente zscore per blocchi separati di abbondanze medie (veramente basso, basso ... med ... alto ... molto alto) –

+0

Perché non usare 'cut (1: nrow (dt), 12)' con Diviso? –

risposta

4

ggplot2 ha un cut_number() funzione di convenienza che farà questo per voi. Se non si desidera sovraccaricare il caricamento del pacchetto, è possibile consultare ggplot2:::breaks per la logica necessaria.

esempio riproducibile rubato da @MichaelChirico:

set.seed(100) 
KK<-130209L; nn<-12L 
library("dplyr") 
dt <- data.frame(mLow1=rnorm(KK),mHigh1=rnorm(KK), 
       mLow2=rnorm(KK),mHigh2=rnorm(KK), 
       meanLow=rnorm(KK),meanHigh=rnorm(KK), 
       fc=rnorm(KK),mean=rnorm(KK)) %>% arrange(mean) 

Con le scuse a coloro che non amano i tubi:

library("ggplot2") ## for cut_number() 
dt %>% mutate(grp=cut_number(mean,12)) %>% 
     group_by(grp) %>% 
     mutate(fc=c(scale(fc))) %>% 
     ungroup() %>%   
     select(-grp) %>%  ## drop grouping variable 
     as.data.frame -> dt2 ## convert back to data frame, assign result 

Si scopre che il c() intorno scale() è necessario - altrimenti la La variabile fc finisce con alcuni attributi che confondono tail() ...

La stessa logica dovrebbe applicarsi all'utilizzo di plyr o della combinazione R split-apply-combine, (la chiave utilizza cut_number() per definire la variabile di raggruppamento).

+0

Mi dispiace, non uso abbastanza dplyr. Sto ottenendo un oggetto di classe '[1]" grouped_df "" tbl_df "" tbl "" data.frame "'. Come faccio a trovarlo in data.frame? Non riesco a visualizzare i dati e non posso fare "as.data.frame" su di esso. –

+0

Ho usato%>% as.data.frame() alla fine e funziona. Grazie. –

+0

In realtà non riesco nemmeno ad accedere alla parte inferiore dei dati. Quando uso tail() mi dà 'Error in FUN (X [[i]], ...): dims [prodotto 10899] non corrispondono alla lunghezza dell'oggetto [130209] ' –

2

Con data.table, si può fare:

library(data.table) 
setDT(dt)[,scale(fc),by=rep(1:nn,each=ceiling(KK/nn),length.out=KK)] 

Qui, KK è 130.209 e nn è 12. dati riproducibili:

set.seed(100) 
KK<-130209L; nn<-12L 
dt<-data.frame(mLow1=rnorm(KK),mHigh1=rnorm(KK), 
       mLow2=rnorm(KK),mHigh2=rnorm(KK), 
       meanLow=rnorm(KK),meanHigh=rnorm(KK), 
       fc=rnorm(KK),mean=rnorm(KK)) 

Quindi nessun bisogno di suddividere i dati e ricombinare.

Se vuoi aggiungere questo al frame di dati invece di estrarlo, è possibile utilizzare l'operatore := da assegnare per riferimento:

setDT(dt)[,fc_scaled:=scale(fc)...] 
+0

Io non sono 100 % sicuro che questo divida i dati nel modo giusto; Penso che tu abbia bisogno di qualcosa come 'rep (1: nn, each = ceiling (KK/nn), length.out = KK)'? –

+0

@BenBolker risolto, grazie. – MichaelChirico

+0

@MichaelChirico Sto ottenendo risultati diversi usando la tua soluzione e quella sopra. –

4

Non sono sicuro che la struttura di dt questioni tanto (se non stai usando nessuno dei suoi valori interni per fare la scissione). questo aiuta?

spl.dt <- split(dt , cut(1:nrow(dt), 12)) 

lapply(spl.dt, my_fun) 
+0

Grazie! Ho provato la tua soluzione, ho cambiato 'lapply' in' ldply' per restituire un data.frame e funziona. –