拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 每次该组出现在大型资料集中时,提取每个组的第一个和最后一个观察值?

每次该组出现在大型资料集中时,提取每个组的第一个和最后一个观察值?

白鹭 - 2022-03-11 2101 0 0

我有一个大型的鱼检测资料集(约 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 dataSelect 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 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *