R - create sentence ID from column of words

Viewed 37

I have a dataframe (tibble) of words that looks like this.

   text      confidence type          start_time end_time
   <chr>     <chr>      <chr>         <chr>      <chr>   
 1 Angela    0.7482     pronunciation 0.04       0.32    
 2 very      1.0        pronunciation 0.32       0.59    
 3 powerful  1.0        pronunciation 0.59       1.29    
 4 .         0.0        punctuation   NA         NA      
 5 And       1.0        pronunciation 1.3        1.65    
 6 with      1.0        pronunciation 1.65       1.87    
 7 every     1.0        pronunciation 1.88       2.24    
 8 hurricane 1.0        pronunciation 2.24       2.75    
 9 there's   0.8826     pronunciation 2.75       2.96    
10 that      1.0        pronunciation 2.96       3.22    
11 one's     0.6438     pronunciation 3.22       3.73    
12 own       0.748      pronunciation 3.73       4.02    
13 .         0.0        punctuation   NA         NA      
14 It's      0.9278     pronunciation 4.02       4.19    
15 usually   0.851      pronunciation 4.19       4.51    

I am trying to create a sentence ID value so that I can group the words into sentences. I'd like the IDs to begin/end to end at type = punctuation.

   text      confidence type          start_time end_time sentence_id
   <chr>     <chr>      <chr>         <chr>      <chr>          <dbl>
 1 Angela    0.7482     pronunciation 0.04       0.32               1
 2 very      1.0        pronunciation 0.32       0.59               1
 3 powerful  1.0        pronunciation 0.59       1.29               1
 4 .         0.0        punctuation   NA         NA                 1
 5 And       1.0        pronunciation 1.3        1.65               2
 6 with      1.0        pronunciation 1.65       1.87               2
 7 every     1.0        pronunciation 1.88       2.24               2
 8 hurricane 1.0        pronunciation 2.24       2.75               2
 9 there's   0.8826     pronunciation 2.75       2.96               2
10 that      1.0        pronunciation 2.96       3.22               2
11 one's     0.6438     pronunciation 3.22       3.73               2
12 own       0.748      pronunciation 3.73       4.02               2
13 .         0.0        punctuation   NA         NA                 2
14 It's      0.9278     pronunciation 4.02       4.19               3
15 usually   0.851      pronunciation 4.19       4.51               3

I am sure there is a relatively easy way to do this, but I can't quite figure it out. Does anyone have any suggestions? In case it helps, here is the dput:

structure(list(text = c("Angela", "very", "powerful", ".", "And", 
"with", "every", "hurricane", "there's", "that", "one's", "own", 
".", "It's", "usually"), confidence = c("0.7482", "1.0", "1.0", 
"0.0", "1.0", "1.0", "1.0", "1.0", "0.8826", "1.0", "0.6438", 
"0.748", "0.0", "0.9278", "0.851"), type = c("pronunciation", 
"pronunciation", "pronunciation", "punctuation", "pronunciation", 
"pronunciation", "pronunciation", "pronunciation", "pronunciation", 
"pronunciation", "pronunciation", "pronunciation", "punctuation", 
"pronunciation", "pronunciation"), start_time = c("0.04", "0.32", 
"0.59", NA, "1.3", "1.65", "1.88", "2.24", "2.75", "2.96", "3.22", 
"3.73", NA, "4.02", "4.19"), end_time = c("0.32", "0.59", "1.29", 
NA, "1.65", "1.87", "2.24", "2.75", "2.96", "3.22", "3.73", "4.02", 
NA, "4.19", "4.51")), row.names = c(NA, -15L), class = c("tbl_df", 
"tbl", "data.frame"))
3 Answers

One dplyr option could be:

df %>%
 mutate(sentence_id = rev(cumsum(rev(type) == "punctuation")),
        sentence_id = max(sentence_id) - sentence_id + 1)

   text      confidence type          start_time end_time sentence_id
   <chr>     <chr>      <chr>         <chr>      <chr>          <dbl>
 1 Angela    0.7482     pronunciation 0.04       0.32               1
 2 very      1.0        pronunciation 0.32       0.59               1
 3 powerful  1.0        pronunciation 0.59       1.29               1
 4 .         0.0        punctuation   <NA>       <NA>               1
 5 And       1.0        pronunciation 1.3        1.65               2
 6 with      1.0        pronunciation 1.65       1.87               2
 7 every     1.0        pronunciation 1.88       2.24               2
 8 hurricane 1.0        pronunciation 2.24       2.75               2
 9 there's   0.8826     pronunciation 2.75       2.96               2
10 that      1.0        pronunciation 2.96       3.22               2
11 one's     0.6438     pronunciation 3.22       3.73               2
12 own       0.748      pronunciation 3.73       4.02               2
13 .         0.0        punctuation   <NA>       <NA>               2
14 It's      0.9278     pronunciation 4.02       4.19               3
15 usually   0.851      pronunciation 4.19       4.51               3

Functioning code, split into multiple columns so that you could understand my though process

library(tidyverse)

df_example <- structure(list(text = c("Angela", "very", "powerful", ".", "And", 
                        "with", "every", "hurricane", "there's", "that", "one's", "own", 
                        ".", "It's", "usually"), confidence = c("0.7482", "1.0", "1.0", 
                                                                "0.0", "1.0", "1.0", "1.0", "1.0", "0.8826", "1.0", "0.6438", 
                                                                "0.748", "0.0", "0.9278", "0.851"), type = c("pronunciation", 
                                                                                                             "pronunciation", "pronunciation", "punctuation", "pronunciation", 
                                                                                                             "pronunciation", "pronunciation", "pronunciation", "pronunciation", 
                                                                                                             "pronunciation", "pronunciation", "pronunciation", "punctuation", 
                                                                                                             "pronunciation", "pronunciation"), start_time = c("0.04", "0.32", 
                                                                                                                                                               "0.59", NA, "1.3", "1.65", "1.88", "2.24", "2.75", "2.96", "3.22", 
                                                                                                                                                               "3.73", NA, "4.02", "4.19"), end_time = c("0.32", "0.59", "1.29", 
                                                                                                                                                                                                         NA, "1.65", "1.87", "2.24", "2.75", "2.96", "3.22", "3.73", "4.02", 
                                                                                                                                                                                                         NA, "4.19", "4.51")), row.names = c(NA, -15L), class = c("tbl_df", 
"tbl", "data.frame"))

df_example %>% 
  mutate(end_of_line = text %>% str_detect("\\."),
         line_row = end_of_line * row_number(),
         line_to_fill = if_else(line_row == 0,NA_integer_,line_row)) %>% 
  fill(line_to_fill,.direction = "up") %>%
  mutate(no_na = line_to_fill %>% replace_na("last_case")) %>% 
  group_by(no_na) %>% 
  mutate(word_number = row_number()) %>% 
  select(-end_of_line,-line_row,-line_to_fill,-no_na)
#> Adding missing grouping variables: `no_na`
#> # A tibble: 15 x 7
#> # Groups:   no_na [3]
#>    no_na     text      confidence type          start_time end_time word_number
#>    <chr>     <chr>     <chr>      <chr>         <chr>      <chr>          <int>
#>  1 4         Angela    0.7482     pronunciation 0.04       0.32               1
#>  2 4         very      1.0        pronunciation 0.32       0.59               2
#>  3 4         powerful  1.0        pronunciation 0.59       1.29               3
#>  4 4         .         0.0        punctuation   <NA>       <NA>               4
#>  5 13        And       1.0        pronunciation 1.3        1.65               1
#>  6 13        with      1.0        pronunciation 1.65       1.87               2
#>  7 13        every     1.0        pronunciation 1.88       2.24               3
#>  8 13        hurricane 1.0        pronunciation 2.24       2.75               4
#>  9 13        there's   0.8826     pronunciation 2.75       2.96               5
#> 10 13        that      1.0        pronunciation 2.96       3.22               6
#> 11 13        one's     0.6438     pronunciation 3.22       3.73               7
#> 12 13        own       0.748      pronunciation 3.73       4.02               8
#> 13 13        .         0.0        punctuation   <NA>       <NA>               9
#> 14 last_case It's      0.9278     pronunciation 4.02       4.19               1
#> 15 last_case usually   0.851      pronunciation 4.19       4.51               2

Created on 2020-06-18 by the reprex package (v0.3.0)

we can use cumsum

   df$id <-  cumsum(df$type == "punctuation")+1

# A tibble: 15 x 6
   text      confidence type          start_time end_time    id
   <chr>     <chr>      <chr>         <chr>      <chr>    <dbl>
 1 Angela    0.7482     pronunciation 0.04       0.32         1
 2 very      1.0        pronunciation 0.32       0.59         1
 3 powerful  1.0        pronunciation 0.59       1.29         1
 4 .         0.0        punctuation   <NA>       <NA>         2
 5 And       1.0        pronunciation 1.3        1.65         2
 6 with      1.0        pronunciation 1.65       1.87         2
 7 every     1.0        pronunciation 1.88       2.24         2
 8 hurricane 1.0        pronunciation 2.24       2.75         2
 9 there's   0.8826     pronunciation 2.75       2.96         2
10 that      1.0        pronunciation 2.96       3.22         2
11 one's     0.6438     pronunciation 3.22       3.73         2
12 own       0.748      pronunciation 3.73       4.02         2
13 .         0.0        punctuation   <NA>       <NA>         3
14 It's      0.9278     pronunciation 4.02       4.19         3
15 usually   0.851      pronunciation 4.19       4.51         3
Related