1

I want to extract bigrams from sentences, using the regex described here and store the output to a new column which references the original.

enter image description here

library(dplyr)
library(stringr)
library(splitstackshape)

df  <- data.frame(a =c("apple orange plum"))

# Single Words - Successful
df %>%
  # Base R
  mutate(b =  sapply(regmatches(a,gregexpr("\\w+\\b", a, perl = TRUE)),
                     paste, collapse=";")) %>%
  # Duplicate with Stringr
  mutate(c =  sapply(str_extract_all(a,"\\w+\\b"),paste, collapse=";")) %>%
  cSplit(., c(2,3), sep = ";", direction = "long")

Initially, I thought the problem seemed to be with the regex engine but neither stringr::str_extract_all (ICU) nor base::regmatches (PCRE) works.

# Bigrams - Fails
df %>%
  # Base R
  mutate(b =  sapply(regmatches(a,gregexpr("(?=(\\b\\w+\\s+\\w+))", a, perl = TRUE)),
                     paste, collapse=";")) %>%
  # Duplicate with Stringr
  mutate(c =  sapply(str_extract_all(a,"(?=(\\b\\w+\\s+\\w+))"),paste, collapse=";")) %>%
  cSplit(., c(2,3), sep = ";", direction = "long")

As a result, I'm guessing the problem is probably to do with using a zero-width lookahead around a capturing group. Is there any valid regex in R which will allows these bigrams be extracted?

Julius Vainora
  • 47,421
  • 9
  • 90
  • 102
rsylatian
  • 429
  • 2
  • 14
  • 1
    `str_extract_all` loses all captured submatches. You need `str_match_all`. Note that the first element will always be an empty element as the match is always empty, but the Group 1 value will land in `[,2]`. – Wiktor Stribiżew Jan 22 '19 at 18:56

1 Answers1

1

As @WiktorStribiżew suggested, using str_extract_all helps here. Here's how to apply it with multiple rows in a data frame. Let

(df <- data.frame(a = c("one two three", "four five six")))
#               a
# 1 one two three
# 2 four five six

Then we may do

df %>% rowwise() %>% 
  do(data.frame(., b = str_match_all(.$a, "(?=(\\b\\w+\\s+\\w+))")[[1]][, 2], stringsAsFactors = FALSE))
# Source: local data frame [4 x 2]
# Groups: <by row>
#
# A tibble: 4 x 2
#   a             b        
# * <fct>         <chr>    
# 1 one two three one two  
# 2 one two three two three
# 3 four five six four five
# 4 four five six five six

where stringsAsFactors = FALSE is just to avoid warnings coming from bindings rows.

Julius Vainora
  • 47,421
  • 9
  • 90
  • 102