首页 > 解决方案 > 当两个定界符在字符串中多次出现时,提取两个定界符之间的所有文本

问题描述

我有几行聊天数据,其中包含如下所示的成绩单:

“参与者 1(我):我不知道这个问题的答案。参与者 2:你怎么看?也许是 20%?参与者 2:我也不知道。参与者 1(我):那是我的猜测参与者"

我只想提取前缀后面的文本,Participant 1 (Me):直到它显示Participant 1or Participant 2。紧跟在Participant 1上述分隔符之前的所有文本都应存储在名为 的变量中participant_1_text。我想将所有剩余的文本存储在一个名为 的单独变量中participant_2_text,如下所示:

participant_1_text = "I don't know the answer to this. that was my guess. sure!
participant_2_text = "What do you think?   Maybe 20%? I don't know either. ok, let's go for
it! ...what do you think? ok! aww! sorry!"

因此,参与者 1 的所有文本和参与者 2 的所有文本现在都分开了。

我尝试了类似下面的正则表达式:

(?<=Participant 1)(.*)(?=Participant 2)

但这将匹配这两个分隔符的第一次和最后一次出现之间的所有文本,而不是每次匹配。


编辑:我现在正在尝试采用以下版本的代码并将它们应用于包含大量聊天记录的数据框:

因此,使用@akrun 的代码,我创建了一个函数,将给定的聊天日志分离到my_chatorpartner_chat并返回一个命名列表:

extract_chat <- function(chat_text){
  final_output = chat_text %>% 
    tibble(col1 = chat_text) %>% 
    mutate(col1 = str_replace_all(col1, "Participant", "\nParticipant")) %>% 
    separate_rows(col1, sep="\n") %>% 
    filter(nzchar(col1)) %>% #filter the non-empty strings
    separate(col1, into = c('Participant', "text"), sep=":") %>% 
    group_by(Participant) %>% 
    summarise(text = str_c(text, collapse= ' ')) %>% 
    mutate(Participant = ifelse(str_detect(Participant, "(Me)"), "my_chat_extracted", "partner_chat_extracted")) %>%
    spread(Participant, text)   

  return(list(my_chat_extracted = final_output$my_chat_extracted,
              partner_chat_extracted = final_output$partner_chat_extracted))
}

这似乎工作正常,但我不确定如何改变我的数据框中的实际列来使用这个函数。

这是要使用的 data.frame 的示例:

str1 <- "Participant 1 (Me): I don't know the answer to this. Participant 2: What do you think? Maybe 20%? Participant 2: I don't know either. Participant 1 (Me): that was my guess Participant 2: ok, let's go for it! ...what do you think? Participant 1 (Me): sure! Participant 2: ok! Participant 2: aww! sorry!"
str2 <- "Participant 1 (Me): Hey, how are you? Participant 2: I'm good, how about you? Participant 2: I'm excited.  Participant 1 (Me): I'm also good."
test = data.frame(chat = c(str1, str2))

我想做类似的事情:

   tester = test %>% 
      rowwise() %>% 
      mutate(my_chat_extracted = extract_chat(chat)$my_chat_extracted)

但这在我的实际数据集上似乎很慢,而且感觉很草率。

标签: rdplyr

解决方案


Participant我们可以在(with )之前插入下一行字符,然后在withstr_replace_all处拆分,去掉任何空格 ( ),将列分成两列 at ,按“参与者”分组,将“文本”字符串分成单个字符串\nseparate_rowsfilternzcharseparate:paste

library(dplyr)
library(stringr)
library(tidyr)
out <- tibble(col1 = str1) %>% 
  mutate(col1 = str_replace_all(col1, "Participant", "\nParticipant")) %>% 
  separate_rows(col1, sep="\n") %>% 
  filter(nzchar(col1)) %>%
  separate(col1, into = c('Participant', "text"), sep=":") %>% 
  group_by(Participant = str_remove(Participant, "\\s*\\(.*")) %>% 
  summarise(text = str_c(text, collapse= ' '))

out
# A tibble: 2 x 2
#  Participant   text                                                                                                                    
#  <chr>         <chr>                                                                                                                   
#1 Participant 1 " I don't know the answer to this.   that was my guess   sure! "                                                        
#2 Participant 2 " What do you think? Maybe 20%?   I don't know either.   ok, let's go for it! ...what do you think?   ok!   aww! sorry!"

将它保存在 a 中可能会更好data.frame,但是如果我们需要单独的对象,请list2envdeframeing之后使用

library(tibble)
list2env(as.list(deframe(out)), .GlobalEnv)
`Participant 1`
#[1] " I don't know the answer to this.   that was my guess   sure! "

数据

str1 <- "Participant 1 (Me): I don't know the answer to this. Participant 2: What do you think? Maybe 20%? Participant 2: I don't know either. Participant 1 (Me): that was my guess Participant 2: ok, let's go for it! ...what do you think? Participant 1 (Me): sure! Participant 2: ok! Participant 2: aww! sorry!"

推荐阅读