2013-03-22 48 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)