Объединение прогонов номинальных переменных

У меня есть набор данных, содержащий диалог между двумя людьми, который был создан во время сеанса чата. Например,

  • "A: Привет"
  • "A: Как вы сегодня"
  • "B: Хорошо. Как дела?"
  • "A: Я хорош"
  • "Cool"

Я хочу создать простую функцию в R, которая объединит строки A до того, как B будет говорить в одну строку, так что у меня есть набор данных, который выглядит так:

  • "A: Привет: Как вы сегодня"
  • "B: Хорошо, как вы?
  • "A: Я хорош"
  • "B: Прохладный"

Я знаю, как объединить/объединить ячейки, но я не уверен, как создать логический оператор, создающий индикатор для строк A, говорит перед B (и наоборот).

Ответ 1

Для этой цели может использоваться функция rle(). Он определяет все прогоны равных значений в заданном векторе.

v1 <- c("A: Hi" , "A: How are you today", "B: Fine. How are you?", 
     "A: I'm good" ,"B: Cool") # input data

speakers <- rle(substring(v1, 1, 1))

Результат функции rle() теперь можно использовать для разделения частей диалога соответственно, а затем объединить их для получения желаемого результата.

ids <- rep(paste(1:length(speakers$lengths)), speakers$lengths) 
unname(sapply(split(v1, ids), function(monologue) {
   # concatenate all statements in a "monologue"
   monologue[-1] <- substring(monologue[-1], 4)
   paste(monologue, collapse=" ")
}))

Результат:

## [1] "A: Hi How are you today"
## [2] "B: Fine. How are you?"
## [3] "A: I'm good"             
## [4] "B: Cool"   

Ответ 2

Опция с использованием data.table. Преобразуйте вектор ( "v1" ) в data.table(setDT). Создайте новую переменную ( "indx" ) на основе префикса ( "A", "B" ). Используя rleid, создайте переменную группировки и paste содержимое переменной "V1" (без префикса) с "indx" для создания ожидаемого результата.

library(data.table)#data.table_1.9.5
setDT(list(v1))[, indx:=sub(':.*', '', V1)][, paste(unique(indx), 
   paste(sub('.:', '', V1), collapse=" "), sep=":") , rleid(indx)]$V1
# [1] "A: Hi  How are you today" "B: Fine. How are you?"   
# [3] "A: I'm good"              "B: Cool"                 

Или вариант использовал бы tstrsplit для разделения столбца "V1" на две группы ( "V1" и "V2" ) на rleid "V1" и paste содержимое "V1" и "V2".

setDT(list(v1))[,tstrsplit(V1, ": ")][, sprintf('%s: %s', unique(V1),
           paste(V2, collapse=" ")), rleid(V1)]$V1
#[1] "A: Hi How are you today" "B: Fine. How are you?"  
#[3] "A: I'm good"             "B: Cool"   

Или вариант с помощью base R

 str1 <- sub(':.*', '', v1)
 indx1 <- cumsum(c(TRUE,indx[-1]!=indx[-length(indx)]))
 str2 <- sub('.*: +', '', v1)
 paste(tapply(str1, indx1, FUN=unique),
    tapply(str2, indx1, FUN=paste, collapse=" "), sep=": ")
 #[1] "A: Hi How are you today" "B: Fine. How are you?"  
 #[3] "A: I'm good"             "B: Cool"   

данные

v1 <- c("A: Hi" , "A: How are you today", "B: Fine. How are you?", 
     "A: I'm good" ,"B: Cool")