[英]R: Split observation values by and aggregate to time intervals
在某些區域( 名稱 )有來自各個觀測點( obs )的鳥類觀測。 記錄了開始時間和結束時間,並使用校正因子重新計算了時間差( diff_corr ),因此它不僅僅是開始-結束間隔的difftime
。
現在,我需要將這些值“拆分”為“不錯”的間隔(15分鍾,例如10:15:00、10:30:00等),然后按區域聚合( 名稱 ),以便能夠以15分鍾為間隔的間隔在這些區域出現鳥類的圖。
因此,更清楚一點:觀察可能始於10:14,一直持續到10:25,因此它跨越了10:00-10:15和10:15-10:30的時間間隔,因此該值應該將我分成幾個部分,並根據他們在該間隔中所分配的部分,將其相應地分配給相應的間隔。
在更復雜的設置中,觀察值可能跨越3或4個間隔,因此該值也必須在此相應地拆分。
最后一步是匯總每個時間間隔的所有觀測部分並繪制它們。
我已經搜索了幾天的解決方案,但是只發現了非常簡單的示例,其中間隔通過cut
和breaks
進行了重新排列,但從未找到如何處理關聯值的示例,而是簡單的頻率計數。
示例數據:
structure(list(obs = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c("b",
"C2", "Dürnberg2"), class = "factor"), name = c("C2", "C2",
"C2", "C2", "C2", "C2", "C2", "C2", "C2", "b", "981", "1627",
"b", "b", "981", "1627", "b", "b", "b", "b"), start = structure(c(1495441500,
1495441590, 1495441650, 1495441680, 1495447380, 1495447410, 1495447530,
1495447560, 1495447580, 1496996580, 1496996580, 1496996580, 1496996760,
1496996820, 1496996820, 1496996820, 1496997180, 1496997300, 1496997420,
1496998260), class = c("POSIXct", "POSIXt"), tzone = ""), end = structure(c(1495441590,
1495441650, 1495441680, 1495441800, 1495447410, 1495447530, 1495447560,
1495447580, 1495447620, 1496996760, 1496996760, 1496996760, 1496996820,
1496997180, 1496997180, 1496997180, 1496997300, 1496997420, 1496997540,
1496998320), class = c("POSIXct", "POSIXt"), tzone = ""), diff_corr = c(1.46739130434783,
0.978260869565217, 0.489130434782609, 1.95652173913043, 0.489130434782609,
1.95652173913043, 0.489130434782609, 0.326086956521739, 0.652173913043478,
2.96703296703297, 2.96703296703297, 2.96703296703297, 0.989010989010989,
5.93406593406593, 5.93406593406593, 5.93406593406593, 1.97802197802198,
1.97802197802198, 1.97802197802198, 0.989010989010989)), .Names = c("obs",
"name", "start", "end", "diff_corr"), row.names = c("1", "9",
"7", "8", "3", "2", "4", "5", "6", "13", "13.1", "13.2", "22",
"11", "11.1", "11.2", "12", "23", "15", "16"), class = "data.frame")
ps我確實很難為我的問題正確命名,所以任何提示(不僅限於此)都受到高度贊賞
一個小例子的新嘗試:按間隔比例將值分配給間隔(然后求和等於間隔)
start end value new values in new 15-min-intervals
10:03:00 10:14:00 11 ---> 10:00:00 = 11
10:14:00 10:16:00 2 ---> 10:00:00 = 1 ; 10:15:00 = 1
10:00:00 10:35:00 40 ---> 10:00:00 = 40/35*15 ; 10:15:00 = 40/35*15 ; 10:30:00 = 40/35*5
10:15:00 10:30:00 12 ---> 10:15:00 = 12
這既緩慢又笨拙,但也許會有所幫助。 按名稱和15分鍾間隔計算計數和加權diff_corr總和:
library(dplyr)
range <- seq.POSIXt(min(df$start)-(15*60), max(df$end)+(15*60), by = "15 min")
df$totalDuration <- as.numeric(as.difftime(df$end-df$start),units=c("secs"))
out <- NULL
for (r in 1:length(range)){
subset <- df %>% filter( (start >= (range[r]-(15*60)) & start<range[r]) |
(end>= (range[r]-(15*60)) & end<range[r] ) |
(end > range[r] & start < range[r])) %>%
mutate(bin=range[r],
duration = ifelse(start>=(range[r]-(15*60)) & end<range[r],totalDuration,
ifelse(start>=(range[r]-(15*60)),as.numeric(as.difftime(range[r]-start),units="secs"),
ifelse(end<range[r],
as.numeric(as.difftime(end-(range[r]-(15*60))),units="secs"),
as.numeric(as.difftime(range[r]-(range[r]-(15*60))),units="secs")
)))
) %>%
mutate (diff_corr_W = diff_corr*(duration/as.double(totalDuration, units='secs'))) %>%
group_by(bin,name) %>% summarise(count=n(),
diff_corr_sum = sum(diff_corr_W)) %>% ungroup()
if (is.null(out)){
out <- subset
} else {
out <- rbind(out,subset)
}
}
> out
# A tibble: 9 x 4
bin name count diff_corr_sum
* <dttm> <chr> <int> <dbl>
1 2017-05-22 04:40:00 C2 4 4.891304
2 2017-05-22 06:10:00 C2 5 3.913043
3 2017-06-09 04:25:00 1627 1 1.978022
4 2017-06-09 04:25:00 981 1 1.978022
5 2017-06-09 04:25:00 b 1 1.978022
6 2017-06-09 04:40:00 1627 2 6.923077
7 2017-06-09 04:40:00 981 2 6.923077
8 2017-06-09 04:40:00 b 6 13.846154
9 2017-06-09 04:55:00 b 1 0.989011
這是一個data.table
方法,它允許您使用SQL類型的查詢來排序/過濾數據並執行操作。
數據
> p
obs name start end diff_corr
1: C2 C2 2017-05-22 04:25:00 2017-05-22 04:26:30 1.4673913
2: C2 C2 2017-05-22 04:26:30 2017-05-22 04:27:30 0.9782609
3: C2 C2 2017-05-22 04:27:30 2017-05-22 04:28:00 0.4891304
4: C2 C2 2017-05-22 04:28:00 2017-05-22 04:30:00 1.9565217
5: C2 C2 2017-05-22 06:03:00 2017-05-22 06:03:30 0.4891304
6: C2 C2 2017-05-22 06:03:30 2017-05-22 06:05:30 1.9565217
7: C2 C2 2017-05-22 06:05:30 2017-05-22 06:06:00 0.4891304
8: C2 C2 2017-05-22 06:06:00 2017-05-22 06:06:20 0.3260870
9: C2 C2 2017-05-22 06:06:20 2017-05-22 06:07:00 0.6521739
10: b b 2017-06-09 04:23:00 2017-06-09 04:26:00 2.9670330
11: b 981 2017-06-09 04:23:00 2017-06-09 04:26:00 2.9670330
12: b 1627 2017-06-09 04:23:00 2017-06-09 04:26:00 2.9670330
13: b b 2017-06-09 04:26:00 2017-06-09 04:27:00 0.9890110
14: b b 2017-06-09 04:27:00 2017-06-09 04:33:00 5.9340659
15: b 981 2017-06-09 04:27:00 2017-06-09 04:33:00 5.9340659
16: b 1627 2017-06-09 04:27:00 2017-06-09 04:33:00 5.9340659
17: b b 2017-06-09 04:33:00 2017-06-09 04:35:00 1.9780220
18: b b 2017-06-09 04:35:00 2017-06-09 04:37:00 1.9780220
19: b b 2017-06-09 04:37:00 2017-06-09 04:39:00 1.9780220
20: b b 2017-06-09 04:51:00 2017-06-09 04:52:00 0.9890110
碼
library(data.table)
library(lubridate)
p <- as.data.table(p)
p[, .(new_diff = mean(diff_corr)), .(tme_start = round_date(start, unit = "15min"))]
輸出值
> p[, .(new_diff = mean(diff_corr)), .(tme_start = round_date(start, unit = "15min"))]
tme_start new_diff
1: 2017-05-22 04:30:00 1.2228261
2: 2017-05-22 06:00:00 0.7826087
3: 2017-06-09 04:30:00 3.3626374
4: 2017-06-09 04:45:00 0.9890110
Data.Table在做什么?
由於您不熟悉data.table
,因此這里是對發生的事情的非常簡單的基本描述。 data.table
調用的一般形式為:
DT[select rows, perform operations, group by]
其中DT
是data.table
名稱。 Select rows
是一種邏輯操作,例如說您只希望觀察C2(名稱),則調用將為DT[name == "C2",]
無需執行任何操作,也無需分組。 如果您希望所有name == "C2"
的diff_corr
列的總和,調用將成為DT[name == "C2", list(sum(diff_corr))]
。 除了編寫list()
還可以使用.()
。 現在輸出將只有一行和一列,稱為V1
,這是name == "C2"
時所有diff_corr
的總和。 該列沒有很多信息,因此我們為它分配一個名稱(可以與舊名稱相同): DT[name == "C2", .(diff_corr_sum = sum(diff_corr))]
。 假設您還有一個名為“ mood”的列,該列報告了進行觀察的人的心情,並且可以假設三個值(“ happy”,“ sad”,“ sleepy”)。 您可以按心情“分組”: DT[name == "C2", .(diff_corr_new = sum(diff_corr)), by = .(mood)]
。 輸出將是對應於每種心情的三行和一列diff_corr_new
。 為了更好地理解這一點,請嘗試使用mtcars
這樣的樣本數據集。 您的樣本數據沒有足夠的復雜性等,因此您無法探索所有這些功能。
返回答案-其他變化
從問題或注釋中尚不清楚您是否要基於start
或end
四舍五入。 我使用了前者,但您可以更改它。 上面的示例使用了mean
但是您可以執行可能需要的任何其他操作。 其他列似乎或多或少是多余的,因為它們是字符串,您不能對它們做太多事情。 您可以使用它們在by
條目(代碼的最后一個字段)中進一步對結果進行排序。 以下是分別使用obs
和name
兩個示例。 您也可以將它們全部組合在一起。
> p[, .(new_diff = mean(diff_corr)), .(tme_start = round_date(start, unit = "15min"), obs)]
tme_start obs new_diff
1: 2017-05-22 04:30:00 C2 1.2228261
2: 2017-05-22 06:00:00 C2 0.7826087
3: 2017-06-09 04:30:00 b 3.3626374
4: 2017-06-09 04:45:00 b 0.9890110
> p[, .(new_diff = mean(diff_corr)), .(tme_start = round_date(start, unit = "15min"), name)]
tme_start name new_diff
1: 2017-05-22 04:30:00 C2 1.2228261
2: 2017-05-22 06:00:00 C2 0.7826087
3: 2017-06-09 04:30:00 b 2.6373626
4: 2017-06-09 04:30:00 981 4.4505495
5: 2017-06-09 04:30:00 1627 4.4505495
6: 2017-06-09 04:45:00 b 0.9890110
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.