9

How can I split a character column into 3 columns using %, -, and + as the possible delimiters, keeping the delimiters in the new columns?

Example Data:

data <- data.table(x=c("92.1%+100-200","90.4%-1000+200", "92.8%-200+100", "99.2%-500-200","90.1%+500-200"))

Example desired data:

data.desired <- data.table(x1=c("92.1%", "90.4%", "92.8%","99.2%","90.1%")
                           , x2=c("+100","-1000","-200","-500","+500")
                           , x3=c("-200","+200","+100","-200","-200"))

Happy to award the points for a good answer and some help on this one!

Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
Neal Barsch
  • 2,810
  • 2
  • 13
  • 39

3 Answers3

6

We may use separate from tidyr for splitting and a positive lookahead as to keep the delimiters:

data %>% separate(x, c("x1", "x2", "x3"), sep = "(?=\\+|-)")
#       x1    x2   x3
# 1: 92.1%  +100 -200
# 2: 90.4% -1000 +200
# 3: 92.8%  -200 +100
# 4: 99.2%  -500 -200
# 5: 90.1%  +500 -200

That is, note that splitting simply by \\+|- we would get

data %>% separate(x, c("x1", "x2", "x3"), sep = "\\+|-")
#       x1   x2  x3
# 1: 92.1%  100 200
# 2: 90.4% 1000 200
# 3: 92.8%  200 100
# 4: 99.2%  500 200
# 5: 90.1%  500 200

Using (?=\\+|-) split at "nothing" in case right after that we have + or - (which are not matched).

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

In data.table the equivalent is tstrsplit:

data[, c("x1","x2","x3") := tstrsplit(x, "(?<=.)(?=[+-])", perl=TRUE) ]
data
#                x    x1    x2   x3
#1:  92.1%+100-200 92.1%  +100 -200
#2: 90.4%-1000+200 90.4% -1000 +200
#3:  92.8%-200+100 92.8%  -200 +100
#4:  99.2%-500-200 99.2%  -500 -200
#5:  90.1%+500-200 90.1%  +500 -200
thelatemail
  • 91,185
  • 12
  • 128
  • 188
3

Here is an option using base R

cbind(data, read.csv(text = gsub("(?=[+-])", ",", data$x, perl = TRUE), 
    header = FALSE, stringsAsFactors = FALSE, col.names = c('x1', 'x2', 'x3')))
#                x    x1    x2   x3
#1:  92.1%+100-200 92.1%   100 -200
#2: 90.4%-1000+200 90.4% -1000  200
#3:  92.8%-200+100 92.8%  -200  100
#4:  99.2%-500-200 99.2%  -500 -200
#5:  90.1%+500-200 90.1%   500 -200
akrun
  • 874,273
  • 37
  • 540
  • 662