在R语言中跨分组生成不重置序列的发言轮次列
为DataFrame创建发言轮次标识列(连续发言归为同一轮)
需求说明
需要为以下示例DataFrame生成turn列,规则为:同一发言者的连续多行语句算作同一轮次;当该发言者非连续地再次发言时,轮次递增。
示例数据集:
df <- data.frame( line = c(1:9), speaker = c("nick", "nick", "nick", "bob", "nick", "ann", "ann", "nick", "bob"), sentence = c("hi", "how are you?", "what's up?", "i'm good", "me too", "hi guys", "any plans for the weekend", "no", "ya, the movies"), turn = c(1, 1, 1, 2, 3, 4, 4, 5, 6))
现有尝试的问题
- 方法1:
group_by(speaker) %>% mutate(turn2 = cur_group_id())
该方法按发言者名称分配固定组ID,同一发言者无论何时发言都对应同一个编号,无法满足"非连续发言时轮次递增"的要求。 - 方法2:
seq_along(speaker)
单纯按行号生成序列,会把同一发言者的连续行拆分为不同轮次,不符合需求。
正确解决方案
使用dplyr实现
通过判断当前行与上一行的发言者是否变化,生成新轮次标记后累加,得到正确的轮次编号:
library(dplyr) df <- df %>% # 标记新轮次:第一行默认是新轮次,后续行若发言者与上一行不同则标记为1 mutate(new_turn = case_when( row_number() == 1 ~ 1, speaker != lag(speaker) ~ 1, TRUE ~ 0 )) %>% # 累加标记得到最终轮次 mutate(turn_correct = cumsum(new_turn)) %>% # 移除中间辅助列(可选) select(-new_turn)
使用base R实现
如果不想依赖dplyr,也可以用base R完成:
# 生成新轮次标记 df$new_turn <- c(1, as.integer(df$speaker[-1] != df$speaker[-nrow(df)])) # 累加得到轮次编号 df$turn_correct <- cumsum(df$new_turn) # 删除辅助列 df$new_turn <- NULL
验证结果
执行上述代码后,turn_correct列将与示例中的turn列完全一致,满足轮次标识需求。
内容的提问来源于stack exchange,提问作者user10240216
相关产品推荐
相关产品推荐

