2013-03-22 19 views
7

Mam ramkę danych i próbuję utworzyć nową zmienną w ramce danych, która zawiera kwantyle zmiennej ciągłej var1, dla każdego poziomu współczynnika strata.Kwantyle według poziomów czynników w R

# some data 
set.seed(472) 
dat <- data.frame(var1 = rnorm(50, 10, 3)^2, 
        strata = factor(sample(LETTERS[1:5], size = 50, replace = TRUE)) 
       ) 

# function to get quantiles 
qfun <- function(x, q = 5) { 
    quantile <- cut(x, breaks = quantile(x, probs = 0:q/q), 
     include.lowest = TRUE, labels = 1:q) 
    quantile 
} 

Próbowałem użyć dwóch metod, z których żadna nie daje użytecznych wyników. Po pierwsze, próbowałem za pomocą aggregate zastosować qfun na każdym poziomie strata:

qdat <- with(dat, aggregate(var1, list(strata), FUN = qfun)) 

ta odsyła quantiles przez poziom czynnika, ale wynik jest trudny do zmuszania powrotem do ramki danych (na przykład za pomocą unlist nie linię nowa wartość zmiennej z poprawnymi wierszami w ramce danych).

Drugie podejście to zrobić w etapach:

tmp1 <- with(dat, split(var1, strata)) 
tmp2 <- lapply(tmp1, qfun) 
tmp3 <- unlist(tmp2) 
dat$quintiles <- tmp3 

Ponownie, oblicza quantiles odpowiednio do każdego poziomu czynnika, ale oczywiście, podobnie jak w aggregate nie są w odpowiedniej kolejności w dane rama. Możemy to sprawdzić, umieszczając kwantylowe "bin" w ramce danych.

# get quantile bins 
qfun2 <- function(x, q = 5) { 
    quantile <- cut(x, breaks = quantile(x, probs = 0:q/q), 
     include.lowest = TRUE) 
    quantile 
} 

tmp11 <- with(dat, split(var1, strata)) 
tmp22 <- lapply(tmp11, qfun2) 
tmp33 <- unlist(tmp22) 
dat$quintiles2 <- tmp33 

Wiele wartości var1 są poza pojemników z quantile2. Czuję, że brakuje mi czegoś prostego. Wszelkie sugestie będą bardzo mile widziane.

Odpowiedz

8

Myślę, że problemem jest to, że tak naprawdę nie chce agregować, ale używać ave (lub data.table lub plyr)

qdat <- transform(dat, qq = ave(var1, strata, FUN = qfun)) 

#using plyr 
library(plyr) 

qdat <- ddply(dat, .(strata), mutate, qq = qfun(var1)) 

#using data.table (my preference) 


dat[, qq := qfun(var1), by = strata] 

Kruszywo zwykle oznacza powrót do obiektu, który jest mniejszy niż w oryginale. (Inthis przypadku były coraz data.frame gdzie x był list z 1 element dla każdej warstwy

+0

(+1) dla 3 różnych metod – ndoogan

+0

@mnel Dzięki bardzo wiedziałem, że musi być brakuje czegoś proste - ja zawsze zapomnieć o ' ave'. – Chris

1

Zastosowanie ave w ramce dat danych Pełny przykład ze swoimi symulowanych danych i qfun funkcję:..

# some data 
set.seed(472) 
dat <- data.frame(var1 = rnorm(50, 10, 3)^2, 
       strata = factor(sample(LETTERS[1:5], size = 50, replace = TRUE)) 
      ) 

# function to get quantiles 
qfun <- function(x, q = 5) { 
    quantile <- cut(x, breaks = quantile(x, probs = 0:q/q), 
     include.lowest = TRUE, labels = 1:q) 
    quantile 
} 

A mój dodatek ...

dat$q <- ave(dat$var1,dat$strata,FUN=qfun) 
Powiązane problemy