Align strings of a dataframe in columns in r

We can do this by first melting the dataset, extract the numeric index from the elements, create a row/column index based on that and assign the elements to a matrix created based on the max value of the index.

library(reshape2)
d1 <- na.omit(transform(melt(as.matrix(df1)), v1 = as.numeric(sub("\\D+", "", value))))
m1 <- matrix("", nrow = max(d1$Var1), ncol = max(d1$v1))
m1[as.matrix(d1[c("Var1", "v1")])]  <- as.character(d1$value) 
d2 <- as.data.frame(m1[,!!colSums(m1!="")])
colnames(d2) <- paste0("col", seq_along(d2))
d2
#     col1     col2     col3     col4
#1 notst-s1 notst-s2 notst-x3         
#2 notst-s1          notst-x3 notst-a5
#3          notst-s2          notst-a5
#4                   notst-x3 notst-a5

Matrix indexing might make this a possibility:

sel <- dat!=""
unq <- unique(dat[sel])
mat <- matrix(NA, nrow=nrow(dat), ncol=length(unq))

mat[cbind(row(dat)[sel],  match(dat[sel], unq) )] <- dat[sel]

#     [,1]       [,2]       [,3]       [,4]      
#[1,] "notst-s1" "notst-s2" "notst-x3" NA        
#[2,] "notst-s1" NA         "notst-x3" "notst-a5"
#[3,] NA         "notst-s2" NA         "notst-a5"
#[4,] NA         NA         "notst-x3" "notst-a5"

Where dat was imported as:

dat <- read.table(text="
    col1       col2       col3 
notst-s1   notst-s2   notst-x3
notst-s1   notst-x3   notst-a5   
notst-s2   notst-a5
notst-x3   notst-a5",header=TRUE,fill=TRUE,stringsAsFactors=FALSE)