You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R中重构独角鲸行为数据以关联起止时间

问题

我有一份记录独角鲸行为的数据集,包含8头鲸鱼的ID(whaleID)、多种行为类型(behaviour),每头鲸鱼可与其他0头、部分或全部鲸鱼互动(modID),每个行为事件的开始/结束状态(status)对应以秒为单位的时间(time_s)。数据由行为记录程序生成,每个事件的起止时间分属不同行。

示例数据集:

library(dplyr)
df <- data.frame(whaleID = c('c','a','b','c','c','a','b','c','c','c','b','c','c','b',
                             'b','b','b','a','b','a','b','b','b','b','c','c'),
                 status = c('start','start','start','stop','start','stop','stop','stop',
                            'start','stop','start','start','stop','stop',
                            'start','stop','start','start','stop','stop',
                            'start','stop','start','stop','start','stop'),
                 time_s = c(40.554,44.801,44.801,60.300,76.053,87.302,87.302,87.302,
                            41.056,42.801,45.304,54.800,56.871,75.054,
                            92.798,94.801,98.844,101.676,105.052,108.160,
                            113.918,118.914,132.170,136.799,248.227,252.568),
                 modID = c('d','b','a','d','d','b','a','d','d','d','a','d','d','a',
                           'a,c','a,c','a','b','a','b','','','','','',''),
                 behaviour = c('contact','contact','contact','contact','contact','contact','contact','contact',
                               'rub','rub','rub','rub','rub','rub',
                               'ventral','ventral','ventral','ventral','ventral','ventral',
                               'erect','erect','erect','erect','erect','erect')) %>% 
  arrange(time_s)

需求:将每个行为事件整合为包含起止时间的单行记录,期望输出如下:

df2 <- data.frame(whaleID = c('c','a','b','c','c','b','c','b','b','a','b','b','c'),
                  start = c(40.554,44.801,44.801,76.053,41.056,45.304,54.800,
                            92.798,98.844,101.676,113.918,132.170,248.227),
                  stop = c(60.300,87.302,87.302,87.302,42.801,75.054,56.871,
                           94.801,105.052,108.160,118.914,136.799,252.568),
                  modID = c('d','b','a','d','d','a','d','a,c','a','b','','',''),
                  behaviour = c('contact','contact','contact','contact','rub','rub','rub',
                                'ventral','ventral','ventral','erect','erect','erect')) %>% 
  arrange(start)

我尝试过在reframe、summarize中嵌套case_when,以及使用pivot_wider,但都没成功,尝试的代码如下:

dfTime <- df %>% 
  group_by(whaleID, behaviour, modID) %>% 
  reframe(start = case_when(status == "START" & min(time_s) ~ time_s),
          stop = case_when(status == "STOP" & min(time_s)~ time_s)) %>%
  ungroup()
解决方案

核心思路是给每个成对的start/stop事件分配唯一分组ID,精准匹配同一事件的起止时间。以下提供两种可行方法:

方法一:使用pivot_wider

library(dplyr)
library(tidyr)

df2 <- df %>%
  # 按鲸鱼ID、行为、互动对象分组,给每个start事件生成递增的分组ID
  group_by(whaleID, behaviour, modID) %>%
  mutate(event_id = cumsum(status == "start")) %>%
  ungroup() %>%
  # 转换为宽表,将start/stop状态转为列
  pivot_wider(
    id_cols = c(whaleID, behaviour, modID, event_id),
    names_from = status,
    values_from = time_s,
    values_fn = first  # 确保每个分组仅取一个时间值
  ) %>%
  # 移除多余分组ID,按开始时间排序
  select(-event_id) %>%
  arrange(start)

方法二:使用summarize(无需tidyr)

df2 <- df %>%
  group_by(whaleID, behaviour, modID) %>%
  mutate(event_id = cumsum(status == "start")) %>%
  # 基于新增的事件ID分组,提取起止时间
  group_by(whaleID, behaviour, modID, event_id) %>%
  summarize(
    start = time_s[status == "start"],
    stop = time_s[status == "stop"],
    .groups = "drop"
  ) %>%
  arrange(start)

两种方法均可生成目标输出,解决了原代码中未区分同一鲸鱼同一行为下多个独立事件的问题,通过event_id将成对的start/stop行绑定为同一事件记录。

内容的提问来源于stack exchange,提问作者Ghazam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 20:27:03