Finding the rank of positions of characters within strings

Viewed 25

I want to find the position of certain strings within a larger string and then rank them based on what comes first.

Example: in a set of 3 strings, I want to find the order that the strings PR, FR, and VG occur. I then want to put that into a dataframe which indicates the rank of each sub-string's position in the larger string. This will then be used in a re-ordering process.

fullStrings <- c(' FR Banana VG Carrot VG Celery PR Chicken ', ' VG Broccoli PR Tofu VG Celery FR Apple ', ' PR Pork VG Brussels Sprouts FR Orange VG Carrot ')
findStrings <- c(' PR ', ' FR ', ' VG ')

I first attempted to use str_locate_all (eg str_locate_all(pattern = ' VG ', mealDF$meals)) and I think it could work, but I was having issues translating what it was spitting out. Here's my desired outcome:

string <- c(meals[1], meals[2], meals[3])
PRpos <- c(4, 2, 1)
FRpos <- c(1, 4, 3)
VG1pos <- c(2, 1, 2)
VG2pos <- c(3, 3, 4)

foodLocations <- data.frame(string, PRpos, FRpos, VG1pos, VG2pos)
foodLocations
                                             string PRpos FRpos VG1pos VG2pos
1         FR Banana VG Carrot VG Celery PR Chicken      4     1      2      3
2            VG Brocoli PR Tofu VG Celery FR Apple      2     4      1      3
3  PR Pork VG Brussels Sprouts FR Orange VG Carrot      1     3      2      4
1 Answers

Here's one option. It uses Vectorize to allow base::regexpr to work on vectors of inputs. I think the output is much simpler than stringr::str_locate_all.

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(tidyr)

fullStrings <- c(' FR Banana VG Carrot VG Celery PR Chicken ', ' VG Broccoli PR Tofu VG Celery FR Apple ', ' PR Pork VG Brussels Sprouts FR Orange VG Carrot ')
findStrings <- c(' PR ', ' FR ', ' VG ')

df <- expand.grid(fullString = fullStrings, findString = findStrings)

vregexpr <- Vectorize(regexpr)
df <- mutate(df, index = vregexpr(findString, fullString))

df %>%
  group_by(fullString) %>%
  mutate(index = rank(index)) %>%
  ungroup() %>%
  pivot_wider(names_from = findString, values_from = index)
#> # A tibble: 3 × 4
#>   fullString                                          ` PR ` ` FR ` ` VG `
#>   <fct>                                                <dbl>  <dbl>  <dbl>
#> 1 " FR Banana VG Carrot VG Celery PR Chicken "             3      1      2
#> 2 " VG Broccoli PR Tofu VG Celery FR Apple "               2      3      1
#> 3 " PR Pork VG Brussels Sprouts FR Orange VG Carrot "      1      3      2

Created on 2022-09-16 by the reprex package (v2.0.1)

Related