每次该组出现在大型数据集中时,提取每个组的第一个和最后一个观察值?
Extract the first and last observation of each group, every time that group appears within a large dataset?
我有一个大型的鱼类检测数据集(约 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 站时再次检测到第一次和最后一次。
我看过 and Select the first and last row by group in a data frame 等问题和其他类似问题,但其中 none 占第 2(第 3、4、n... 次)小组(在我的案例:站)出现在数据中。
如果您能提供帮助,请告诉我。谢谢你。
(这是我关于堆栈溢出的第一个问题,任何对以后问题的提示都有帮助)
我这里的方法是标记鱼每次换站的情况,然后计算这些换站的累计次数。然后我们可以按鱼和# of station 更改分组,并过滤每个的第一个和最后一个。
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
这是一个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
我有一个大型的鱼类检测数据集(约 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 站时再次检测到第一次和最后一次。
我看过
如果您能提供帮助,请告诉我。谢谢你。 (这是我关于堆栈溢出的第一个问题,任何对以后问题的提示都有帮助)
我这里的方法是标记鱼每次换站的情况,然后计算这些换站的累计次数。然后我们可以按鱼和# of station 更改分组,并过滤每个的第一个和最后一个。
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
这是一个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