Using gregexpr.
z <- dat$categories
t(do.call(cbind, lapply(regmatches(z, gregexpr(z, pa='\\w')), combn, 2)))
# [,1] [,2]
# [1,] "A" "B"
# [2,] "A" "C"
# [3,] "A" "D"
# [4,] "B" "C"
# [5,] "B" "D"
# [6,] "C" "D"
# [7,] "A" "F"
# [8,] "A" "X"
# [9,] "A" "G"
# [10,] "F" "X"
# [11,] "F" "G"
# [12,] "X" "G"
# [13,] "B" "Y"
# [14,] "B" "X"
# [15,] "B" "D"
# [16,] "Y" "X"
# [17,] "Y" "D"
# [18,] "X" "D"
By ID's
do.call(rbind.data.frame, by(dat, dat$categories, \(x) {
z <- x$categories
cbind(id=x$id,
t(do.call(cbind, lapply(regmatches(z, gregexpr(z, pa='\\w')), combn, 2))))
}))
# id X1 X2
# A, B, C, D.1 1 A B
# A, B, C, D.2 1 A C
# A, B, C, D.3 1 A D
# A, B, C, D.4 1 B C
# A, B, C, D.5 1 B D
# A, B, C, D.6 1 C D
# A, F, X, G.1 2 A F
# A, F, X, G.2 2 A X
# A, F, X, G.3 2 A G
# A, F, X, G.4 2 F X
# A, F, X, G.5 2 F G
# A, F, X, G.6 2 X G
# B, Y, X, D.1 3 B Y
# B, Y, X, D.2 3 B X
# B, Y, X, D.3 3 B D
# B, Y, X, D.4 3 Y X
# B, Y, X, D.5 3 Y D
# B, Y, X, D.6 3 X D
Note: "R version 4.1.2 (2021-11-01)"
Data:
dat <- structure(list(id = 1:3, categories = c("A, B, C, D", "A, F, X, G",
"B, Y, X, D")), class = "data.frame", row.names = c(NA, -3L))