2017-05-03 139 views
2

我试图按照预先确定的断点将数据按年分组。我可以很容易地使用cut()函数在特定年份执行此操作,但我正在努力使其在data.table函数中工作。这里是测试数据:R data.table lapply with cut函数

set.seed(4) 
YR = data.table(yr=1962:2015) 
ID = data.table(id=10001:11000) 
DT <- YR[,as.list(ID), by = yr] # intentional cartesian join 
# now add data 
DT[,`:=` (ratio = rep(sample(10),each=2700)+rnorm(nrow(DT)))] 

这给出了三列:年,id和比率,后者是我想分组的数据。

现在,这里是每年的断点:所以每年1962至2015年为

DTy <- data.table(matrix(rep(1:10,each=nrow(YR)),nrow(YR),10)+rnorm(54)/10) 
DTy[,yr := 1962:2015] 

有一个临界值集合。以1962年为例,这里是我想做的事情:

group <- cut(DT[yr==1962,ratio],DTy[yr==1962, -c("yr")], labels = FALSE) 

这里是它的样子。

ratio <- DT[yr==1962,ratio] 
DTy[yr==1962,-c("yr")] 
test <- data.table(ratio,group) 
test[,yr:=1962] 
> test 
     ratio group yr 
    1: 6.689275  6 1962 
    2: 4.718753  4 1962 
    3: 5.786855  5 1962 
    4: 7.896540  7 1962 
    5: 7.776863  7 1962 
    ---      
996: 6.176614  6 1962 
997: 7.689046  7 1962 
998: 4.652658  4 1962 
999: 7.075622  7 1962 
1000: 5.543791  5 1962 

我尝试这样做:

# merge two datasets together 
newDT <- merge(x = DT, y = DTy, by = c("yr")) 
# get names of columns with breakpoints 
cnames <- names(newDT)[newDT[,grep("^V", names(newDT))]] 
# apply the cut function by year. 
newDT[,groupt := lapply(.SD, cut, as.vector(unique(.SD[,cnames,with=FALSE])), labels = FALSE, include.lowest = TRUE), by = .(year), .SDcols = c("ratio", cnames)] 

但我得到这个错误:

Error in `[.data.table`(newDT, , `:=`(groupt, lapply(.SD, cut, as.vector(unique(.SD[, : 
    column or expression 1 of 'by' or 'keyby' is type closure. Do not quote column names. Usage: DT[,sum(colC),by=list(colA,month(colB))] 

我真的不知道这意味着什么。我试图使用.SD像一个data.table,但需要不同的列为cut()函数的不同部分,我不知道如何通过lapply传递它们。

+0

都是伟大的解决方案 - 我喜欢第二个,因为它是最接近我在做什么。 –

回答

1

这里是我通过简单地修改代码:

newDT <- merge(x = DT, y = DTy, by = c("yr")) 
# get names of columns with breakpoints 
cnames <- names(newDT)[grep("^V", names(newDT))] 

# apply the cut function by year. 
res <- newDT[, group := cut(ratio, unlist(.SD[1]), labels = F), 
      by = .(yr), .SDcols = cnames][ 
       , .(yr, id, ratio, group)] 

#   yr id  ratio cutted 
# 1: 1962 10001 6.689275  6 
# 2: 1962 10002 4.718753  4 
# 3: 1962 10003 5.786855  5 
# 4: 1962 10004 7.896540  7 
# 5: 1962 10005 7.776863  7 
# ---        
# 53996: 2015 10996 10.613272  NA 
# 53997: 2015 10997 11.260932  NA 
# 53998: 2015 10998 8.591909  8 
# 53999: 2015 10999 9.143039  9 
# 54000: 2015 11000 7.470945  7 
1

下面是一个使用一个连接方法和by=.EACHI

DT[DTy, on="yr", 
    cutted := cut(ratio, c(i.V1, i.V2, i.V3, i.V4, i.V5, i.V6, i.V7, i.V8, i.V9, i.V10), 
       labels=FALSE), by=.EACHI] 

这里,data.table与断裂连接到由今年的主要data.table,然后一个新的变量与:=使用分配切。这分别适用于使用by=.EAHCHI将值加入的每个组。

这将返回

head(DT) 
    yr id ratio cutted 
1: 1962 10001 6.689275  6 
2: 1962 10002 4.718753  4 
3: 1962 10003 5.786855  5 
4: 1962 10004 7.896540  7 
5: 1962 10005 7.776863  7 
6: 1962 10006 6.566604  6 

您可以使用mgetls与模式搜索,从而无需枚举cut,断裂参数使用的变量。

DT[DTy, on="yr", cutted := cut(ratio, c(mget(ls(pattern="^i\\.V\\d+$"))), labels=FALSE), 
    by=.EACHI]