tidyr::separate
makes separating columns simple by allowing you to pass an integer index of split position, including negatively indexed from the end of the string. (Regex works as well, of course.)
library(tidyr)
b %>% separate(name, into = c('name', 'age'), sep = -4, convert = TRUE)
## height name age
## 1 190 John Smith 34
## 2 165 Mr.Turner 54
## 3 174 Antonio P. 23
## 4 176 John Brown 31
or separate by the final space:
b %>% separate(name, into = c('name', 'age'), sep = '\s(?=\S*?$)', convert = TRUE)
which returns the same thing.
In base R, it's a bit more work:
b$name <- as.character(b$name)
split_name <- strsplit(b$name, '\s(?=\S*?$)', perl = TRUE)
split_name <- do.call(rbind, split_name)
colnames(split_name) <- c('name', 'age')
b <- data.frame(b[-2], split_name, stringsAsFactors = FALSE)
b$age <- type.convert(b$age)
b
## height name age
## 1 190 John Smith 34
## 2 165 Mr.Turner 54
## 3 174 Antonio P. 23
## 4 176 John Brown 31
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…