【问题标题】:How to apply a function to a subset of data, where the subset is specified by another data.table?如何将函数应用于数据子集,其中子集由另一个 data.table 指定?
【发布时间】:2019-03-28 16:26:05
【问题描述】:

我有一个 data.table l1,其中包含三列,Minute,Posixct 表示时间,group_cor 表示我的值,我想根据 data.table s1 计算特定时间间隔内 group_cor 的唯一值的数量。在我的原始数据集中,我有大约 1500000 个数据行,持续大约 12 天(结构为 l1),所以我正在寻找一种快速的方法来处理所有这些数据。

       Posixct            group_cor   Minute
 1: 2017-08-11 13:31:36       185     2017-08-11 13:31:00
 2: 2017-08-11 13:31:36       185     2017-08-11 13:31:00
 3: 2017-08-11 13:31:36       185     2017-08-11 13:31:00
 4: 2017-08-11 13:31:37       186     2017-08-11 13:31:00
 5: 2017-08-11 13:31:37       186     2017-08-11 13:31:00
 6: 2017-08-11 13:31:37       187     2017-08-11 13:31:00
 7: 2017-08-11 13:31:37       187     2017-08-11 13:31:00
 8: 2017-08-11 13:31:37       187     2017-08-11 13:31:00
 9: 2017-08-11 13:31:37       187     2017-08-11 13:31:00

这是 s1,其中 start 表示时间间隔的开始,结束时间间隔的结束。每个时间间隔为一分钟,此窗口一次移动 1 秒。

                     start                 end
  1: 2017-08-11 13:31:36 2017-08-11 13:32:36
  2: 2017-08-11 13:31:37 2017-08-11 13:32:37
  3: 2017-08-11 13:31:38 2017-08-11 13:32:38
  4: 2017-08-11 13:31:39 2017-08-11 13:32:39
  5: 2017-08-11 13:31:40 2017-08-11 13:32:40   

我尝试使用 data.table 将 No 列添加到 data.table s1 中,我使用“on”参数指定时间窗口。

oma <- function(x) length(unique(x))
s1[ l1, No:=oma(group_cor), on=c('start<Posixct','end>=Posixct')]

然而,这给了

> s1
               start                 end      No
  1: 2017-08-11 13:31:36 2017-08-11 13:32:36 188
  2: 2017-08-11 13:31:37 2017-08-11 13:32:37 188
  3: 2017-08-11 13:31:38 2017-08-11 13:32:38 188
  4: 2017-08-11 13:31:39 2017-08-11 13:32:39 188
  5: 2017-08-11 13:31:40 2017-08-11 13:32:40 188 

所有时间窗口的 No 列都是 188,这是不正确的(我不知道这个值来自哪里..)

> range(s1$No)
 [1] 188 188   

我知道每分钟唯一值的数量,新的 No 应该与它们相似

> tapply(l1$group_cor, l1$Minute,oma)
2017-08-11 13:31:00 2017-08-11 13:32:00 2017-08-11 13:33:00 2017-08-11     13:34:00 
             11                  17                  18                  17 
2017-08-11 13:35:00 2017-08-11 13:36:00 2017-08-11 13:37:00 2017-08-11 13:38:00 
             21                  22                  23                  22 
2017-08-11 13:39:00 2017-08-11 13:40:00 
             20                  22     

我做错了什么?任何帮助将不胜感激!还建议我如何以另一种方式做到这一点。非常感谢。

【问题讨论】:

  • 我想也许你需要一个by=.EACHI 在你的连接中,否则它只是在连接中使用完整的group_cor 向量。顺便说一句,oma 已经在 data.table 中为uniqueN
  • 感谢您的建议和指出uniqueN。我尝试运行 s1[ l, No:=uniqueN(group_cor), on=c('start&lt;Posixct','end&gt;=Posixct'), by=.EACHI] 但我没有得到正确的答案。我没有得到Noas 1 列中的所有值。它现在在做什么?
  • 我从未想出纯 data.table 解决方案,但最终使用 d &lt;- lapply(seq_len(nrow(s1)),function(n) { a &lt;- l1[Posixct &gt; s1$start[n] &amp; Posixct &lt;= s1$end[n], .(No = uniqueN(group_cor))] }) 并将列表 d(在我将其转换为矢量之后)添加到 data.table s1跨度>

标签: r data.table subset


【解决方案1】:

如果我理解正确并且弗兰克在 cmets 中提到的内容,那么您正在寻找

intvl[dat, cnt := uniqueN(group_cor), by=.EACHI, on=c('start<Posixct','end>=Posixct')][, 
   cnt := replace(cnt, is.na(cnt), 0L)]

输出:

                 start                 end cnt
1: 2017-08-11 13:31:36 2017-08-11 13:32:36   1
2: 2017-08-11 13:31:37 2017-08-11 13:32:37   0
3: 2017-08-11 13:31:38 2017-08-11 13:32:38   0
4: 2017-08-11 13:31:39 2017-08-11 13:32:39   0
5: 2017-08-11 13:31:40 2017-08-11 13:32:40   0

数据:

library(data.table)
dat <- fread("Posixct,group_cor,Minute
2017-08-11 13:31:36,185,2017-08-11 13:31:00
2017-08-11 13:31:36,185,2017-08-11 13:31:00
2017-08-11 13:31:36,185,2017-08-11 13:31:00
2017-08-11 13:31:37,186,2017-08-11 13:31:00
2017-08-11 13:31:37,186,2017-08-11 13:31:00
2017-08-11 13:31:37,187,2017-08-11 13:31:00
2017-08-11 13:31:37,187,2017-08-11 13:31:00
2017-08-11 13:31:37,187,2017-08-11 13:31:00
2017-08-11 13:31:37,187,2017-08-11 13:31:00")
cols <- c("Posixct", "Minute")
dat[, (cols) := lapply(.SD, as.POSIXct, format="%Y-%m-%d %H:%M:%S"), .SDcols=cols]

intvl <- fread("start,end
2017-08-11 13:31:36,2017-08-11 13:32:36
2017-08-11 13:31:37,2017-08-11 13:32:37
2017-08-11 13:31:38,2017-08-11 13:32:38
2017-08-11 13:31:39,2017-08-11 13:32:39
2017-08-11 13:31:40,2017-08-11 13:32:40")
cols <- c("start", "end")
intvl[, (cols) := lapply(.SD, as.POSIXct, format="%Y-%m-%d %H:%M:%S"), .SDcols=cols]

我认为您以前无法获得它是因为您的 R 会话中有太多不同的变量。这将有助于重新启动会话并使用干净的数据和间隔。

【讨论】:

  • 我在数据上运行了s1[l1, cnt := uniqueN(group_cor), by=.EACHI, on=c('start&lt;Posixct','end&gt;=Posixct')][,cnt := replace(cnt, is.na(cnt), 0L)],但没有得到我想要的输出。输出看起来像这样start end cnt 1: 2017-08-11 13:31:36 2017-08-11 13:32:36 1 2: 2017-08-11 13:31:37 2017-08-11 13:32:37 1 3: 2017-08-11 13:31:38 2017-08-11 13:32:38 1 4: 2017-08-11 13:31:39 2017-08-11 13:32:39 1 5: 2017-08-11 13:31:40 2017-08-11 13:32:40 1 6: 2017-08-11 13:31:41 2017-08-11 13:32:41 1
  • 并且取值范围是1到1range(s1$cnt) [1] 1 1
  • 我想要的输出看起来像这样start end cnt 1: 2017-08-11 13:31:36 2017-08-11 13:32:36 22 2: 2017-08-11 13:31:37 2017-08-11 13:32:37 20 3: 2017-08-11 13:31:38 2017-08-11 13:32:38 20 4: 2017-08-11 13:31:39 2017-08-11 13:32:39 21 5: 2017-08-11 13:31:40 2017-08-11 13:32:40 21 6: 2017-08-11 13:31:41 2017-08-11 13:32:41 20 当我使用我之前写过的 lapply 方法时可以得到这个输出,但是当我在原始数据集上运行它时需要几个小时。您还有其他建议吗?
  • 在我想要的输出中,cnt值的范围应该是 15 到 24。当我使用 lapply 方法 unique(s1$cnt) [1] 22 20 21 19 18 17 16 15 23 24
  • 在显示@chinsoon12 的输出中,第一行的cntvalue 应该是3 而不是1,因为group_corvalues 185,186 和187 出现在这个时间间隔@987654334 @。下一行应该有一个cnt2,因为只有group_cor值186和187出现在时间间隔2017-08-11 13:31:37 2017-08-11 13:32:37中。其余时间间隔超出范围(我只向您展示了一小部分数据)。感谢您的时间和帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-08
  • 2021-11-17
  • 2017-06-18
  • 1970-01-01
  • 2020-08-11
  • 2011-11-20
  • 1970-01-01
相关资源
最近更新 更多