Объединить текстовые строки на основе условий

#r #dplyr

#r #dplyr

Вопрос:

У меня есть транскрипции речи, подобные этому (воспроизводимые данные ниже):

 df
   line speaker                                  utt_CA                   timestamp
3  0002  ID07.C they 're like [at the] lowest thing so= 00:00:06.045 - 00:00:10.930
5  0003  ID07.B                                   [mhm] 00:00:09.572 - 00:00:10.022
7  0004    <NA>                                 (0.070) 00:00:10.930 - 00:00:11.000
9  0005  ID07.B                           =°thank you°= 00:00:11.000 - 00:00:11.610
11 0006    <NA>                                 (0.065) 00:00:11.610 - 00:00:11.675
13 0007  ID07.C           [but I think] it will be fine 00:00:11.675 - 00:00:14.530
15 0008  ID07.B                      [°°that 's fine°°] 00:00:13.390 - 00:00:14.100
17 0009    <NA>                                 (0.230) 00:00:14.530 - 00:00:14.760
19 0010  ID07.B                             °thank you° 00:00:14.760 - 00:00:15.310
21 0011    <NA>                                 (0.845) 00:00:15.310 - 00:00:16.155
23 0012  ID07.B             [good thing that you (...)] 00:00:16.155 - 00:00:17.125
25 0013  ID07.C         [and that was ac]tually perfect 00:00:16.155 - 00:00:18.850
 

Когда a speaker делает паузу, эта пауза, например (0.070) , записывается в следующей строке utt_CA , поэтому речь одного и того же speaker человека оказывается распределенной по нескольким строкам. Мне нужно перенести всю речь по одному speaker , включая их паузы, в одну и ту же строку. Однако, когда пауза возникает перед тем, как следующий speaker начинает говорить, тогда пауза не должна быть объединена, а должна оставаться в отдельной строке. Везде, где текстовые строки объединяются, значения line и timestamp должны быть изменены соответствующим образом.

Отправной точкой для изменения другими может быть этот метод:

 library(dplyr)
df %>%
  group_by(notna = cumsum(!is.na(speaker))) %>%
  summarize(
    line = first(line), 
    speaker = first(speaker), 
    utterance = paste(utt_CA, collapse = " "), 
    timestamp = paste(unlist(strsplit(timestamp, "[- ] "))[c(1, n()*2)], collapse = " - "),
    .groups = "drop"
  ) %>%
  select(-notna) 
 

Это приближается, но недостаточно близко; желаемый результат таков:

 0001  ID07.C  they 're like [at the] lowest thing so=                                      00:00:06.045 - 00:00:10.930
0002  ID07.B  [mhm] (0.070) =°thank you°=                                                  00:00:09.572 - 00:00:11.610
0003    <NA>  (0.065)                                                                      00:00:11.610 - 00:00:11.675
0004  ID07.C  [but I think] it will be fine                                                00:00:11.675 - 00:00:14.530
0005  ID07.B  [°°that 's fine°°] (0.230) °thank you° (0.845) [good thing that you (...)]   00:00:13.390 - 00:00:17.125
0006  ID07.C  [and that was ac]tually perfect                                              00:00:16.155 - 00:00:18.850
 

Помощь очень ценится!

Воспроизводимые данные:

 df <- structure(list(line = c("0002", "0003", "0004", "0005", "0006", 
                              "0007", "0008", "0009", "0010", "0011", "0012", "0013"), speaker = c("ID07.C", 
                                                                                                   "ID07.B", NA, "ID07.B", NA, "ID07.C", "ID07.B", NA, "ID07.B", 
                                                                                                   NA, "ID07.B", "ID07.C"), utt_CA = c("they 're like [at the] lowest thing so=", 
                                                                                                                                       "[mhm]", "(0.070)", "=°thank you°=", "(0.065)", "[but I think] it will be fine", 
                                                                                                                                       "[°°that 's fine°°]", "(0.230)", "°thank you°", "(0.845)", 
                                                                                                                                       "[good thing that you (...)]", "[and that was ac]tually perfect"
                                                                                                   ), timestamp = c("00:00:06.045 - 00:00:10.930", "00:00:09.572 - 00:00:10.022", 
                                                                                                                    "00:00:10.930 - 00:00:11.000", "00:00:11.000 - 00:00:11.610", 
                                                                                                                    "00:00:11.610 - 00:00:11.675", "00:00:11.675 - 00:00:14.530", 
                                                                                                                    "00:00:13.390 - 00:00:14.100", "00:00:14.530 - 00:00:14.760", 
                                                                                                                    "00:00:14.760 - 00:00:15.310", "00:00:15.310 - 00:00:16.155", 
                                                                                                                    "00:00:16.155 - 00:00:17.125", "00:00:16.155 - 00:00:18.850")), row.names = c(3L, 
                                                                                                                                                                                                  5L, 7L, 9L, 11L, 13L, 15L, 17L, 19L, 21L, 23L, 25L), class = "data.frame")
 

Комментарии:

1. @akrun Я хотел сказать спасибо за ваш код. Мне удалось заменить первый бит, который не работал с моими фактическими данными, и объединить этот бит со вторым большим битом вашего кода — кажется, это сработало прекрасно! Если вы захотите опубликовать свой ответ еще раз, я был бы рад принять его и проголосовать за него!