作者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://www.ptt.cc/bbs/R_Language/M.1569535893.A.084.html
※ 編輯: beatnik (36.234.37.26 臺灣), 09/27/2019 06:12:17
→ celestialgod: 因為你用的是data.frame 不是data.table 09/27 10:10
沒錯, 我後來有發現我耍笨了....= ="
謝謝指正!
→ celestialgod: 另外 我有點看不懂你說的意思 不超過六小時的最後一 09/27 10:20
→ 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
→ celestialgod: 樓上你只考慮了跟前一筆.... 09/27 19:05
→ andrew43: 我想到針對時間做 hclust + cutree 來針對時間分群。 09/28 02:18
→ andrew43: 另外,發問者你說6小時應該說錯了,可以大E修文一下。 09/28 02:43
→ andrew43: 嗯,我解錯了。後來補充說明中說了只要和前一筆比就行了 09/28 02:58
→ andrew43: 若如此,我的解中 "complete" 改成 "single" 09/28 03:02
→ beatnik: 感謝以上大大, 我會再來好好試著解看看 09/29 06:53