在R的data.table中,如何使用不同间隔值的findInterval()函数?

5

我很久之前就问过这个问题,但还没有找到答案。我不知道在stackoverflow上是否正规,但我想再发一遍。

我有一个R中的data.table,我想创建一个新列,为每个年/月对应的价格找到区间。

可重复示例:

set.seed(100)
DT <- data.table(year=2000:2009, month=1:10,  price=runif(5*26^2)*100)
intervals <- list(year=2000:2009, month=1:10, interval = sort(round(runif(9)*100)))
intervals <- replicate(10, (sample(10:100,100, replace=T)))
intervals <- t(apply(intervals, 1, sort))
intervals.dt <- data.table(intervals)
intervals.dt[, c("year", "month") := list(rep(2000:2009, each=10), 1:10)]
setkey(intervals.dt, year, month)
setkey(DT, year, month)

我刚尝试了以下操作:
  • 按月/年合并DTintervals.dt数据表,
  • 创建一个新的intervalsstring列,其中包含所有V*列到一个列字符串中(我承认这不是很优雅),最后
  • 将其子字符串为向量,以便我可以在findInterval()中使用它,但该解决方案并不适用于每一行!
所以,在此之后:
DT <- merge(DT, intervals.dt)
DT <- DT[, intervalsstring := paste(V1, V2, V3, V4, V5, V6, V7, V8, V9, V10)]
DT <- DT[, c("V1", "V2", "V3", "V4", "V5", "V6", "V7", "V8", "V9", "V10") := NULL]
DT[, interval := findInterval(price, strsplit(intervalsstring, " ")[[1]])]

我明白了

> DT
      year month     price               intervalsstring interval
   1: 2000     1 30.776611 12 21 36 46 48 51 63 72 91 95        2
   2: 2000     1 62.499648 12 21 36 46 48 51 63 72 91 95        6
   3: 2000     1 53.581115 12 21 36 46 48 51 63 72 91 95        6
   4: 2000     1 48.830599 12 21 36 46 48 51 63 72 91 95        5
   5: 2000     1 33.066053 12 21 36 46 48 51 63 72 91 95        2
---                                                            
3376: 2009    10 33.635924 12 40 45 48 50 65 75 90 96 97        2
3377: 2009    10 38.993769 12 40 45 48 50 65 75 90 96 97        3
3378: 2009    10 75.065820 12 40 45 48 50 65 75 90 96 97        8
3379: 2009    10  6.277403 12 40 45 48 50 65 75 90 96 97        0
3380: 2009    10 64.189162 12 40 45 48 50 65 75 90 96 97        7

对于第一行来说是正确的,但对于最后一行(或其他行)则不正确。例如,对于第3380行,价格约为64.19应该在第5个区间而不是第7个。我猜我的错误是通过上一条命令,找到区间只依赖于intervalsstring的第一行。

谢谢!


你是否查看了?data.table并确保你理解每一个参数?我只是简单地浏览了一下这个问题,我的第一个想法是想知道你是否知道rollwhich和可能的foverlaps() - Matt Dowle
1个回答

10
你的主要问题是你没有为每个组做 findInterval。但我也不明白创建那个大的合并的 data.table,或者使用 paste/strsplit 的意义所在。这是我会做的:
DT[, interval := findInterval(price,
                              intervals.dt[.BY][, V1:V10]),
     by = .(year, month)][]
#      year month     price interval
#   1: 2000     1 30.776611        2
#   2: 2000     1 62.499648        6
#   3: 2000     1 53.581115        6
#   4: 2000     1 48.830599        5
#   5: 2000     1 33.066053        2
#  ---                              
#3376: 2009    10 33.635924        1
#3377: 2009    10 38.993769        1
#3378: 2009    10 75.065820        7
#3379: 2009    10  6.277403        0
#3380: 2009    10 64.189162        5

请注意,intervals.dt[.BY] 是一个键控子集。

1
不错的 .BY 示例。已添加到 https://github.com/Rdatatable/data.table/issues/1363。 - Matt Dowle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接