Объединение прогонов номинальных переменных
У меня есть набор данных, содержащий диалог между двумя людьми, который был создан во время сеанса чата. Например,
- "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")