作者beatnik (碧妮可)
看板R_Language
标题Re: [问题] 以时间间隔为条件,抽取资料
时间Fri Sep 27 06:11:31 2019
感谢原原po的发问以及c大的解答
正好也遇到类似的状况
但照着做之後,
# 计算时间差,以小时表示
DT[ , diffTime := difftime(time, time[min(k, .N)], units="hours"), by = ind]
这一段都会跳出error......
Error in `[.data.frame`(DT, , `:=`(diffTime, difftime(time, time[min(k, :
unused argument (by = ind)
我是将自身资料撷取出来, 栏位名全都改成跟c大的资料一样
用c大产生的资料下去跑没问题
但内容换成我的资料就会错误
我的资料格式如下:
ind是"character", time是"POSIXct" "POSIXt",
照理应该是符合规则, 不知卡在哪?
然後我要保留的条件与原文也有所不同
以原文为例:
个体A 2012/10/11 20:00 实验资料OOXX
个体A 2012/10/11 23:00 实验资料OOXX
个体A 2012/10/12 03:00 实验资料OOXX
个体B 2012/12/11 05:00 实验资料OOXX
个体B 2012/12/11 11:05 实验资料OOXX
个体B 2012/12/11 13:00 实验资料OOXX
个体B 2012/12/11 18:00 实验资料OOXX
个体B 2012/12/11 20:00 实验资料OOXX
A个体保留第一、第三笔资料
B个体保留第一、第二、第四笔资料
我则是要保留相近时间内(与上一笔撷取的时间不超过6小时)的最後一笔
其结果会是: A个体保留第3笔, B个体保留第1、5笔
对於B个体而言
05:00
|----> 间隔大於6小时, 则保留5:00, 下一笔开始为新的区间
11:05
13:00 这几笔彼此与前一笔间隔未超过6小时, 则视为同个区间
18:00 取最後一笔20:00
20:00
这样又该如何调整程式呢??
不知是否有人可以提供建议呢? 非常感谢!
※ 引述《celestialgod (天)》之铭言:
: ※ 引述《anakinyen (我在台北 天气晴)》之铭言:
: : [问题类型]:
: : 程式谘询(我想用R 做某件事情,但是我不知道要怎麽用R 写出来)
: : [软体熟悉度]:
: : 新手,只会套用package
: : [问题叙述]:
: : 我有一批动物研究的资料
: : 资料大致长这个样子,共有12只个体一万多笔
: : 个体A 2012/10/11 20:00 实验资料OOXX
: : 个体A 2012/10/11 23:00 实验资料OOXX
: : 个体A 2012/10/12 03:00 实验资料OOXX
: : 个体B 2012/12/11 05:00 实验资料OOXX
: : 个体B 2012/12/11 11:05 实验资料OOXX
: : 个体B 2012/12/11 13:00 实验资料OOXX
: : 个体B 2012/12/11 18:00 实验资料OOXX
: : 个体B 2012/12/11 20:00 实验资料OOXX
: : 由於时间间隔过短的话,资料之间可能有相关性
: : 因此我现在想要设定6小时的阀值,间隔超过6小时的资料才会保留
: : 以上面资料为例
: : A个体保留第一、第三笔资料
: : B个体保留第一、第二、第四笔资料
: : 我的程度是新手,偶尔会拿一些package来套用
: : 请教是否有相关套件或现成code可以用在这个案例
: : 非常感谢~~
: 我用while + data.table做,若用data.frame会复制很多次,效率会不彰
: library(data.table)
: # 产生资料
: numObs <- 50
: numInd <- 5
: DT <- data.table(ind = paste0("A", sample(numInd, numObs, TRUE)),
: time = strptime("2012/12/11", "%Y/%m/%d") +
: sample(86400, numObs, TRUE),
: obs = rnorm(numObs))
: # 排序
: setorder(DT, ind, time, obs)
: # 移除掉时间差小於六小时的
: k <- 1
: while ( TRUE ) {
: # 计算时间差,以小时表示
: DT[ , diffTime := difftime(time, time[min(k, .N)], units="hours"), by = ind]
: # 留下自己那一组
: set(DT, which(DT$diffTime == 0), which(names(DT) == "diffTime"), 1e6)
: # 留下时间差超过六小时的
: DT <- DT[abs(diffTime) > 6, ]
: # 下一组
: k <- k + 1
: # 如果k大於全部组的最大观测值数目就跳离回圈
: if (k > max(DT[ , .(numObsGroup = .N), by = ind]$numObsGroup))
: break
: }
: # 移除diffTime这个变数
: DT[ , diffTime := NULL]
: 五万笔观测值,一千个个体,耗时0.23秒 (平均一个个体50个观测值)
: 五十万笔观测值,一千个个体,耗时0.39秒 (平均一个个体500个观测值)
: 我觉得这个速度应该可以接受
: 不过我的区间只有24小时,所以可能都很快就筛选完了
: 有人可以试试看更长时间的表现
: 有问题或任何人有更好解法,欢迎提供,感谢
: Note: 间隔一百天,五十万笔观测值,一千个个体,耗时18.33秒
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 36.234.37.26 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/R_Language/M.1569535893.A.084.html
※ 编辑: beatnik (36.234.37.26 台湾), 09/27/2019 06:12:17
1F:→ celestialgod: 因为你用的是data.frame 不是data.table 09/27 10:10
没错, 我後来有发现我耍笨了....= ="
谢谢指正!
2F:→ celestialgod: 另外 我有点看不懂你说的意思 不超过六小时的最後一 09/27 10:20
3F:→ celestialgod: 笔 A的话 不是第二笔跟第三笔吗? 09/27 10:22
只要彼此之间不间隔超过所设定之时间(如:6小时)
则都算同一时间区间
A的话, 每一笔都与前一笔不超过6小时
所以取它们的最後一笔--第3笔
这边用6小时举例可能比较难想像
若是以间隔不超过10分钟为条件, 则取连续观测中的最後一笔
如:
13:01
13:05
13:11 v 取这笔(前3笔彼此都不间隔超过10分钟)
14:22 --> 与前笔差10分钟以上, 故视为新一批不同於前面的观测值
14:25 v 取这笔
为何要取最後一笔?
是因为在本案之间隔10分钟内的数值, 可能不具参考性
中间会一直重复测量直到正确为止
所以最後一笔才是我想要的修正後或正确的数值
10分钟以上再出现的数值, 表示又开始测量另一个批次
在短时间内(10分钟内)量很多次後, 一样只抓最後一笔
抱歉有点复杂@@
※ 编辑: beatnik (36.234.37.26 台湾), 09/27/2019 10:52:07
5F:→ celestialgod: 楼上你只考虑了跟前一笔.... 09/27 19:05
6F:→ andrew43: 我想到针对时间做 hclust + cutree 来针对时间分群。 09/28 02:18
8F:→ andrew43: 另外,发问者你说6小时应该说错了,可以大E修文一下。 09/28 02:43
9F:→ andrew43: 嗯,我解错了。後来补充说明中说了只要和前一笔比就行了 09/28 02:58
10F:→ andrew43: 若如此,我的解中 "complete" 改成 "single" 09/28 03:02
11F:→ beatnik: 感谢以上大大, 我会再来好好试着解看看 09/29 06:53