I think most important is to figure out how you managed to get matrix-type columns in the first place and understand whether this was a desired behavior or a side effect of a mistake somewhere earlier.
Given where you are, you can just use c to undo a given column:
df3$v5 <- c(df3$v5)
Or if this is a problem with all columns:
df3[ ] <- lapply(df3, c)
(lapply returns a list of vectors, and when we pass a list via assignment to a data.frame, it interprets each list element as a column; df3[ ] returns all columns of df3. We could also do df3 <- lapply(df3, c), but using [ ] is more robust -- if we make a mistake and somehow return the wrong number of columns, an error will be thrown, where as simply using df3 would have simply overwritten our data.frame silently in case of such an error)
Lastly, if only some columns are matrix-type, we can replace only those columns like so:
mat.cols <- sapply(df3, is.matrix) df3[ , mat.cols] <- lapply(df3[ , mat.cols], c)
As pertains to the relation between this approach and that using as.vector, from ?c:
c is sometimes used for its side effect of removing attributes except names, for example to turn an array into a vector. as.vector is a more intuitive way to do this, but also drops names.
So given that the names don't mean much in this context, c is simply a more concise approach, but the end result is practically identical.