I have a record of conversations between two arbitrary persons A and B.
c1 <- "Person A: blabla...something Person B: blabla something else Person A: OK blabla"
c2 <- "Person A: again blabla Person B: blabla something else Person A: thanks blabla"
The data frame looks like this:
df <- data.frame(id = rbind(123, 345), conversation = rbind(c1, c2))
df
    id                                                                     conversation
c1 123 Person A: blabla...something Person B: blabla something else Person A: OK blabla
c2 345   Person A: again blabla Person B: blabla something else Person A: thanks blabla
Now I would like to extract only the part of person A and put it in a data frame. The result should be:
   id                     person_A
1 123 blabla...something OK blabla
2 345   again blabla thanks blabla
I'm a big fan of solving this sort of problem in a way that gives you access to all the data (that includes Person B's discourse as well).  I love tidyr's extract for this sort of column splitting.  I used to use a do.call(rbind, strsplit())) approach but love how clean the extract approach is.
c1 <- "Person A: blabla...something Person B: blabla something else Person A: OK blabla"
c2 <- "Person A: again blabla Person B: blabla something else Person A: thanks blabla"
c3 <- "Person A: again blabla Person B: blabla something else"
df <- data.frame(id = rbind(123, 345, 567), conversation = rbind(c1, c2, c3))
if (!require("pacman")) install.packages("pacman")
pacman::p_load(dplyr, tidyr)
conv <- strsplit(as.character(df[["conversation"]]), "\\s+(?=Person\\s)", perl=TRUE)
df2 <- df[rep(1:nrow(df), sapply(conv, length)), ,drop=FALSE]
rownames(df2) <- NULL
df2[["conversation"]] <- unlist(conv)
df2 %>%
    extract(conversation, c("Person", "Conversation"), "([^:]+):\\s+(.+)")
##    id   Person          Conversation
## 1 123 Person A    blabla...something
## 2 123 Person B blabla something else
## 3 123 Person A             OK blabla
## 4 345 Person A          again blabla
## 5 345 Person B blabla something else
## 6 345 Person A         thanks blabla
## 7 567 Person A          again blabla
## 8 567 Person B blabla something else
df2 %>%
    extract(conversation, c("Person", "Conversation"), "([^:]+):\\s+(.+)") %>%
    filter(Person == "Person A")    
##    id   Person       Conversation
## 1 123 Person A blabla...something
## 2 123 Person A          OK blabla
## 3 345 Person A       again blabla
## 4 345 Person A      thanks blabla
## 5 567 Person A       again blabla
Or collapse them as you show in the desired output:
df2 %>%
    extract(conversation, c("Person", "Conversation"), "([^:]+):\\s+(.+)") %>%
    filter(Person == "Person A") %>%
    group_by(id) %>%
    select(-Person) %>%
    summarise(Person_A =paste(Conversation, collapse=" "))
##    id                     Person_A
## 1 123 blabla...something OK blabla
## 2 345   again blabla thanks blabla
## 3 567                 again blabla
Edit: In reality I suspect your data has real names like "john Smith" vs. "Person A". If this is the case this initial regex split will capture a first and last name that uses caps followed by a colon:
c1 <- "Greg Smith: blabla...something Sue Williams: blabla something else Greg Smith: OK blabla"
c2 <- "Greg Smith: again blabla Sue Williams: blabla something else Greg Smith: thanks blabla"
c3 <- "Greg Smith: again blabla Sue Williams: blabla something else"
df <- data.frame(id = rbind(123, 345, 567), conversation = rbind(c1, c2, c3))r
conv <- strsplit(as.character(df[["conversation"]]), "\\s+(?=([A-Z][a-z]+\\s+[A-Z][a-z]+:))", perl=TRUE)
df2 <- df[rep(1:nrow(df), sapply(conv, length)), ,drop=FALSE]
rownames(df2) <- NULL
df2[["conversation"]] <- unlist(conv)
df2 %>%
    extract(conversation, c("Person", "Conversation"), "([^:]+):\\s+(.+)")
##    id       Person          Conversation
## 1 123   Greg Smith    blabla...something
## 2 123 Sue Williams blabla something else
## 3 123   Greg Smith             OK blabla
## 4 345   Greg Smith          again blabla
## 5 345 Sue Williams blabla something else
## 6 345   Greg Smith         thanks blabla
## 7 567   Greg Smith          again blabla
## 8 567 Sue Williams blabla something else
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With