我有一个大型的鱼检测资料集(约 300,000 行)。每个检测都有一个日期、一个站点(位置)和一个 tagID,以及许多其他变量,例如温度、深度等。我想在每次鱼访问该站点时提取每个站点的第一个和最后一个检测。最终目标是在每个站点移动之前计算每个站点的驻留时间,并在它回传时再次计算驻留时间。
这是资料的一个小例子
tagID <- c("8272", "8272", "8272", "8272", "8272", "8272", "8272", "8272", "8272", "8272")
date <- c("2020-07-12", "2020-07-12", "2020-07-13", "2020-07-13", "2020-07-16", "2020-07-17", "2020-07-20", "2020-07-29", "2020-07-30", "2020-08-04")
station <- c("4", "4", "4", "5", "5", "6", "6", "6", "4", "4")
temp <- c("10", "9", "11", "12", "10", "12", "11", "12", "12", "9")
depth <- c("6.14", "34.2", "21", "23.5", "15.4", "54", "32.4", "23", "33.3", "32.7")
df <- data.frame(tagID, date, station, temp, depth)
资料框看起来像:
tagID date station temp depth
1 8272 2020-07-12 4 10 6.14
2 8272 2020-07-12 4 9 34.2
3 8272 2020-07-13 4 11 21
4 8272 2020-07-13 5 12 23.5
5 8272 2020-07-16 5 10 15.4
6 8272 2020-07-17 6 12 54
7 8272 2020-07-20 6 11 32.4
8 8272 2020-07-29 6 12 23
9 8272 2020-07-30 4 12 33.3
10 8272 2020-08-04 4 9 32.7
我想找到一种有效的方法来遍历所有 300K 行并提取如下内容:
tagID date station temp depth
1 8272 2020-07-12 4 10 6.14
3 8272 2020-07-13 4 11 21
4 8272 2020-07-13 5 12 23.5
5 8272 2020-07-16 5 10 15.4
6 8272 2020-07-17 6 12 54
8 8272 2020-07-29 6 12 23
9 8272 2020-07-30 4 12 33.3
10 8272 2020-08-04 4 9 32.7
这显示了鱼在第 4 站时的第一次和最后一次检测,然后当鱼在本季晚些时候回到第 4 站时再次进行第一次和最后一次检测。
我查看了诸如Select first and last row from grouped data和Select the first and last row by group in a data frame之类的问题,以及其他类似的问题,但这些问题都没有考虑到第二个(第 3、第 4、第 .. .time)组(在我的例子中:站)出现在资料中。
如果您能提供帮助,请告诉我。谢谢你。(这是我关于堆栈溢位的第一个问题,对未来问题的任何提示都是有帮助的)
uj5u.com热心网友回复:
我在这里的方法是标记鱼更改站点的每个场合,然后计算这些更改的累积次数。然后我们可以按鱼和站点更改数进行分组,并过滤??每个的第一个和最后一个。
library(dplyr)
df %>%
group_by(tagID) %>%
mutate(station_chg = station != lag(station, default = ""),
station_cuml = cumsum(station_chg)) %>%
group_by(tagID, station_cuml) %>%
slice(1, n()) %>%
ungroup()
结果
# A tibble: 8 x 7
tagID date station temp depth station_chg station_cuml
<chr> <chr> <chr> <chr> <chr> <lgl> <int>
1 8272 2020-07-12 4 10 6.14 TRUE 1
2 8272 2020-07-13 4 11 21 FALSE 1
3 8272 2020-07-13 5 12 23.5 TRUE 2
4 8272 2020-07-16 5 10 15.4 FALSE 2
5 8272 2020-07-17 6 12 54 TRUE 3
6 8272 2020-07-29 6 12 23 FALSE 3
7 8272 2020-07-30 4 12 33.3 TRUE 4
8 8272 2020-08-04 4 9 32.7 FALSE 4
uj5u.com热心网友回复:
这是一种data.table
方法。正如@Henrik 在评论中提到的,您可以使用rleid
创建一个新列进行分组,而不是station
用作station
重复值。rleid
. 然后,对于每个组,它将包括第一个和最后一个.N
值。请注意,unique
添加它是为了考虑给定组可能仅存在一行资料的情况。我希望这可能是您的快速解决方案。
library(data.table)
setDT(df)
df[ , id := rleid(station)][ , .SD[unique(c(1, .N))], by = id]
输出
id tagID date station temp depth
1: 1 8272 2020-07-12 4 10 6.14
2: 1 8272 2020-07-13 4 11 21
3: 2 8272 2020-07-13 5 12 23.5
4: 2 8272 2020-07-16 5 10 15.4
5: 3 8272 2020-07-17 6 12 54
6: 3 8272 2020-07-29 6 12 23
7: 4 8272 2020-07-30 4 12 33.3
8: 4 8272 2020-08-04 4 9 32.7
0 评论