2013-03-22 84 views
7

我有一個數據框,我試圖在數據框中創建一個新的變量,該變量的分位數爲連續變量var1,對於因子爲strata的每個級別。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 
} 

我試過使用兩種方法,都沒有產生可用的結果。首先,我試圖使用aggregate申請qfun到的strata每個級別:

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

這將返回由因子水平的分位數,但輸出難以迫使回的數據幀(例如,使用unlist不線新變量的值與數據幀中的正確行一致)。

第二種方法是做到這一點的步驟:

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

同樣,這正確計算位數每個因子的水平,但很明顯,與aggregate他們不是在數據正確的順序幀。我們可以通過將分位數「分檔」放入數據框來檢查。

# 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 

很多var1值都是外面的quantile2垃圾箱的。我覺得我錯過了一些簡單的事情。任何建議將不勝感激。

回答

8

我覺得你的問題是,你真的不想要聚合,但使用ave,(或data.tableplyr

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] 

聚合通常意味着返回一個對象,它是原來的小。 (inthis情況下你得到一個data.frame其中x是爲每層1元的list

+0

(+1)3種不同的方法 – ndoogan 2013-03-22 04:30:17

+0

@mnel感謝這麼多,我知道我一定是簡單的東西 - 我總是忘了' ave'。 – Chris 2013-03-23 01:47:44

1

dat數據幀上使用ave與模擬數據和qfun功能完整的示例:。

# 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 
} 

而我除了...

dat$q <- ave(dat$var1,dat$strata,FUN=qfun)