在data.table

时间:2019-05-06 22:10:11

标签: r data.table intervals

我想按组应用一个函数,该函数根据该组中的值将观察值所属的间隔分配给新变量。我觉得以下代码应该可以工作,但是似乎正在使用整个数据集,而不是组的最大值和最小值。我想念什么?

#require(data.table)
#fake data
set.seed(12345)
df1 <- data.frame(id_f=c(rep("a a",100),rep("b b",100),rep("c c",100)), 
                   L=c(abs(rnorm(100,50,20)),abs(rnorm(100,90,20)),abs(rnorm(100,220,20))), 
                   w=abs(rnorm(300,6,3))) 
dt2 = as.data.table(df1)

#the offending data.table function
dt2[,"bins":= findInterval(L, c((max(L)-min(L))/10*c(1:9)),left.open=T)+1, by=id_f]

编辑:

在“ aa”列中,在“ aa”范围内将有10个等距的bin,并且将为每个原始观测值分配一个bin编号,因为实际数据有6,000个观测值,每个观测值中都有多个成员斌因此输出将类似于:(为简洁起见,这是一个三个时间间隔的示例)

id_f  L    w     bins
a a   1    1.0   1
a a   2    1.1   2
a a   3    5.0   3
b b   3    2.0   1
b b   6    3.5   2
b b   9    7.0   3
c c   10   1.0   1
c c   15   1.5   2
c c   20   6.0   3

我本以为我对findInterval的调用将完成此任务,但是显然,它是从全局数据集中而不是仅从组中提取minmax的。我该如何从组中抢夺minmax,然后用它来计算该组的间隔?

2 个答案:

答案 0 :(得分:1)

我认为在这里使用cut会更容易,只需指定我们想要的breaks的数量

library(data.table)
setDT(dt2)[,"bins":= cut(L, breaks = 10, labels = 1:10), by=id_f]

dt2
#     id_f     L     w bins
#  1:  a a  71.5  2.96    8
#  2:  a a  49.5  3.63    5
#  3:  a a  49.3  6.90    5
#  4:  a a  19.7 10.92    2
#  5:  a a  65.8  9.25    7
# ---                      
#296:  c c 206.0  6.50    4
#297:  c c 224.8  4.04    6
#298:  c c 213.0 10.36    5
#299:  c c 227.4  3.58    6
#300:  c c 224.9  7.12    6

我们也可以在dplyr或基数R中进行

library(dplyr)

dt2 %>%
  group_by(id_f) %>%
  mutate(bins = cut(L, breaks = 10, labels = 1:10))

OR

with(dt2, ave(L, id_f, FUN = function(x) cut(x, breaks = 10, labels = 1:10)))

答案 1 :(得分:0)

您将需要运行表格函数来演示该问题。 by-操作似乎在“起作用”

    > dt2[ , list(mn=min(L), mx=max(L) ), by=id_f]
   id_f         mn       mx
1:  a a   5.462025 104.2456
2:  b b  43.824476 138.4843
3:  c c 168.075002 276.5598
> dt2[ , table(id_f, bins)]
     bins
id_f    1   2   3   4   5   6   7   8   9  10
  a a   3   5  10  10  19  13  21  10   4   5
  b b   0   0   0   0   1   3  10   8  19  59
  c c   0   0   0   0   0   0   0   0   0 100

很明显,由于您没有使用set.seed()

,因此结果会有所不同
png(); par(mfrow=c(3,1)); tapply(df1$L, df1$id_f, hist); dev.off()

enter image description here