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

使用case_when跨多列计算不同call_type的音符时长

声乐音符数据集时长计算解决方案

问题背景

我有一个大型声乐音符数据集,需要根据call_type计算每个音符(行)的时长,编程经验有限。

数据集示例

note_type call_type begin.time end.time
         1   doublet   314.2205 314.2344
         2   doublet   314.2856 314.3273
         3   squeak    316.2678 316.2799
         1   triplet   316.3476 316.3928
         1   triplet   318.4582 318.4713
         2   triplet   318.5413 318.5853

时长计算规则

  • doublet:时长 = note_type2的end.time - note_type1的begin.time
  • squeak:时长 = end.time - begin.time
  • triplet:时长 = 连续3个triplet中第3个音符的end.time - 第1个音符的begin.time

已有代码

all_notes %>%
  mutate(call_dur = case_when(call_type == "doublet" & note_type == "1" ~ (lead(end.time) - begin.time), 
                              call_type == "squeak" ~ (end.time - begin.time)))

目前卡在triplet的计算上,因为triplet的note_type组合不固定(比如1,1,2、1,2,2等),不知道怎么跨3行计算时长,希望得到实现triplet时长计算的方法,最终理想的call_dur列结果如下:

note_type call_type begin.time end.time call_dur
         1   doublet   314.2205 314.2344   0.0139
         2   doublet   314.2856 314.3273   na
         3   squeak    316.2678 316.2799   0.0121
         1   triplet   316.3476 316.3928   2.2377
         1   triplet   318.4582 318.4713   na
         2   triplet   318.5413 318.5853   na

解决方案

可以用dplyr的分组和窗口函数处理triplet的情况,核心是先标记连续的triplet组,再在组内针对性计算时长,完整代码如下:

library(dplyr)

all_notes %>%
  # 标记连续的triplet组:call_type切换时组号递增
  mutate(triplet_group = cumsum(call_type != lag(call_type, default = ""))) %>%
  # 按分组处理时长计算
  group_by(triplet_group) %>%
  mutate(
    call_dur = case_when(
      # 保留原有doublet计算逻辑
      call_type == "doublet" & note_type == "1" ~ lead(end.time) - begin.time,
      # 保留原有squeak计算逻辑
      call_type == "squeak" ~ end.time - begin.time,
      # triplet仅组内第一行计算时长:取组内最后一行的end.time减当前begin.time
      call_type == "triplet" & row_number() == 1 ~ last(end.time) - begin.time,
      # 其余情况设为NA
      TRUE ~ NA_real_
    )
  ) %>%
  ungroup() %>%
  select(-triplet_group) # 移除临时分组列

代码说明

  1. triplet_group列:通过cumsum和lag函数识别连续的triplet片段,确保每一组连续的3个triplet被归为同一组。
  2. 分组计算逻辑:在每个triplet组内,仅给第一行赋值时长,用last(end.time)获取组内最后一个音符的结束时间,减去第一行的开始时间。
  3. 逻辑整合:保留了你已实现的doublet和squeak计算规则,保证整体逻辑统一。

运行这段代码后,即可得到符合预期的call_dur列结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 08:13:14