I've been answering this Creating a dataframe with text from a website and I have experienced an odd case which I cannot wrap my head around.
We have the lines below copied to our clipboard:
Leading Men (Average American male: 5 feet 9.5 inches)
Dolph Lundgren — 6 feet 5 inches
John Cleese — 6 feet 5 inches
Leading Ladies (Average American female: 5 feet 4 inches)
Uma Thurman — 6 feet 0 inches
Brooke Shields — 6 feet 0 inches
I have provided the solution below, which extracts gender from the header line and fills the following lines/rows with that. The issue here's that it extracts the word 'Leading' as well as "gender". I was expecting to be able to use \K (reset match token) to get rid of that, but that does not work.
web.lines <- read.delim("clipboard", header = F) # reading data from clipboard
library(tidyverse)
web.lines %>%
mutate(gender = str_extract(V1, "Leading\\s+\\b(\\w+)\\b")) %>%
fill(gender , .direction = "down") %>%
group_by(gender) %>%
slice(-1) %>% # removing the headers
separate(V1, into = c("Name", "Height"), sep = " — ")
#> # A tibble: 4 x 3
#> # Groups: gender [2]
#> Name Height gender
#> <chr> <chr> <chr>
#> 1 Uma Thurman 6 feet 0 inches Leading Ladies
#> 2 Brooke Shields 6 feet 0 inches Leading Ladies
#> 3 Dolph Lundgren 6 feet 5 inches Leading Men
#> 4 John Cleese 6 feet 5 inches Leading Men
What I have tried was Leading\\s+\\K\\w+ which seems to be working in the demo https://regex101.com/r/pYaW7a/1 but not with str_extract.
You do not need \K in stringr regex functions that do not support it (see the ICU regex syntax documentation), because you have str_match / str_match_all functions.
The \K match reset operator that is supported by PCRE, Perl, Onigmo, Python PyPi regex and Boost regex libraries and thus also available in base R regex functions via perl=TRUE argument, is used to omit some text matched before the current position. The same effect can be achieved with capturing groups. The problem with str_extract and str_extract_all is that they do not keep the captured substrings in the output. str_match/str_match_all keep the captured substrings in their output.
See the R demo:
web.lines %>%
mutate(gender = str_match(V1, "Leading\\s+(\\w+)")[,2]) %>%
fill(gender , .direction = "down") %>%
group_by(gender) %>%
slice(-1) %>% # removing the headers
separate(V1, into = c("Name", "Height"), sep = " — ")
Output:
# A tibble: 4 x 3
# Groups: gender [2]
Name Height gender
<chr> <chr> <chr>
1 Uma Thurman 6 feet 0 inches Ladies
2 Brooke Shields 6 feet 0 inches Ladies
3 Dolph Lundgren 6 feet 5 inches Men
4 John Cleese 6 feet 5 inches Men
Here, str_match(V1, "Leading\\s+(\\w+)")[,2] is used to match and capture one or more word chars after Leading word and one or more whitespaces, and return just the captured value by accessing the item at the [,2] index.
Note word boundaries are redundant here, there is an implicit word boundary between a whitespace and a word char, and a \b after \w+ is also implicitly present.
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