Change position of specific string in a string vector in R using Slice or Stringr?

Viewed 58

This is my vector

my_vec <- letters

Is it possible to put z letter in the 3rd position and letter c in the fourth position using slice (dplyr) or maybe stringr ?

Its a simple permutation.

5 Answers

You can build an "insertion" function yourself:

insert <- function(x, i, j){
  tmp <- x[-i]
  c(tmp[1:(j-1)], x[i], tmp[j:length(tmp)])
}

insert(letters, 26, 3)
# [1] "a" "b" "z" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t"
#[22] "u" "v" "w" "x" "y"

Old answer: You can build a permutation function yourself:

permute <- function(x, i, j) {
  x[c(i, j)] <- x[c(j, i)]
  x} 

permute(letters, 26, 3)
#[1] "a" "b" "z" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u"
#[22] "v" "w" "x" "y" "c"

We can use indexing in base R

my_vec[c(1:2, length(my_vec), 4:length(my_vec)-1)]

-output

[1] "a" "b" "z" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y"

There is also a package function moveMe (from SOfun)

#source("http://news.mrdwab.com/install_github.R")
#install_github("mrdwab/SOfun")
library(SOfun)
moveMe(my_vec, "z before c")
 #[1] "a" "b" "z" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y"

Or if we want to use tidyverse, an option is

library(dplyr)
library(tibble)
as_tibble_row(setNames(my_vec, my_vec)) %>%
  relocate(z, .before = c) %>%
  names
 [1] "a" "b" "z" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y"

For easier control, you can define some vectors that store the information for your transformation.

target_char <- "z"
target_pos <- 3

my_vec <- letters

append(my_vec[my_vec != target_char], target_char, target_pos - 1)

Which is essentially this:

append(my_vec[my_vec != "z"], "z", 2)

Output

 [1] "a" "b" "z" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p"
[18] "q" "r" "s" "t" "u" "v" "w" "x" "y"

Although not terribly efficient, we could use a simple index, where we have the indices of the values to move to the beginning then we can get the remaining index numbers with setdiff:

move_index <- c(1:2, 26, 3)

letters[c(move_index, setdiff(1:26,c(move_index)))]

# [1] "a" "b" "z" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y"

You could do

letters %>% 
  as_tibble() %>% 
  slice(1:2, 26,3:25) %>%   
  pull()
Related