2015-07-31 11 views
5

Mam data.frame z 130.219 wierszy.Jak podzielić ramkę danych według wierszy na porcje n, zastosować funkcję i połączyć?

> 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 

Chcę podzielić data.frame w 12, stosuje się funkcję scale na kolumnie fc a następnie połączyć je. Nie ma tu żadnej zmiennej grupującej, inaczej użyłbym ddply. Ponadto, ponieważ 130,209 nie jest doskonale podzielne przez 12, wynikowy data.frames będzie niezrównoważony, tj. 11 data.frame s będzie miał 10,851 wierszy, a ostatni będzie miał 10 848 wierszy, ale to jest w porządku.

Jak podzielić data.frame przez rząd na kawałki n (w tym przypadku 12), zastosować funkcję, a następnie połączyć je razem? Każda pomoc będzie doceniona.

Aktualizacja: Korzystanie dwa pierwsze rozwiązania, mam różne wyniki: Stosując rozwiązanie @Ben Bolker, w

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 

Korzystanie @ MichaelChirico za odpowiedź:

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

ta liczba wierszy nie jest duża. Dlaczego chcesz używać skali oddzielnie i łączyć wyniki zamiast bezpośrednio skalować kolumnę Fc? –

+0

Chcę kontrolować fc (fałd zmiana) dla średniej obfitości (średnia). Dane są posortowane według średniej w mojej faktycznej ramce danych. Chcę obliczyć Zscore oddzielnie dla oddzielnych porcji średniej obfitości (naprawdę niska, niska ... med ... wysoka ... do bardzo wysokiej) –

+0

Dlaczego nie użyć 'cut (1: nrow (dt), 12)' with rozdzielać? –

Odpowiedz

4

ggplot2 ma cut_number() funkcja wygody, która zrobi to za Ciebie. Jeśli nie chcesz obciążać tej paczki, możesz przejrzeć ggplot2:::breaks dla potrzebnej logiki.

Powtarzalne przykład skradzione @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) 

Z całym szacunkiem dla tych, którzy nie lubią Rury

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 

Okazuje się, że c() wokół scale() jest konieczne - w przeciwnym wypadku Zmienna fc kończy się niektórymi atrybutami, które mylą tail() ...

Ta sama logika powinna mieć zastosowanie do używania plyr lub podstawowego R do stosowania w split-apply-kombajnie (klucz używa cut_number() do zdefiniowania zmiennej grupującej).

+0

Przykro mi, że nie używam dplyr. Otrzymuję obiekt klasy "[1]" grouped_df "" tbl_df "" tbl "" data.frame "'. Jak mogę go pobrać w data.frame? Nie mogę wyświetlić danych i nie mogę wykonać na nich "as.data.frame". –

+0

Użyłem%>% as.data.frame() na końcu i działa. Dzięki. –

+0

Właściwie nie mogę uzyskać dostępu do dolnej części danych. Kiedy używam tail() daje mi to błąd w FUN (X [[i]], ...): dims [produkt 10899] nie pasuje do długości obiektu [130209] ' –

2

Z data.table, można zrobić:

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

Tutaj KK jest 130209 i nn wynosi 12. Powtarzalne dane:

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)) 

Więc nie ma potrzeby, aby podzielić dane i rekombinacji.

Jeśli chcesz dodać do ramki danych, a nie tylko wyodrębnić go, można użyć operatora := przypisać odnośnik:

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

Nie jestem 100 % na pewno, że podzieli dane we właściwy sposób; Myślę, że potrzebujesz czegoś takiego jak 'rep (1: nn, each = ceiling (KK/nn), length.out = KK)'? –

+0

@BenBolker naprawiony, dzięki. – MichaelChirico

+0

@MichaelChirico Otrzymuję różne wyniki za pomocą twojego rozwiązania i powyższego. –

4

Nie jestem pewna struktura dt sprawach tyle (jeśli nie używasz żadnej z wewnętrznych wartości do podziału). czy to pomaga?

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

lapply(spl.dt, my_fun) 
+0

Dzięki! Próbowałem Twojego rozwiązania, zmieniłem 'lapply' na' ldply', aby zwrócić data.frame & działa. –

Powiązane problemy