You can use regexp_extract
as @Prem suggested but with a different regex pattern, depending on what you need:
# do not keep the first two groups, just what follows, the surname:
pattern = r'(?:(?:Dr|Mrs?|Ms|Miss|Master|Rev|Capt|Mlle|Col|Major|Sir|Lady|Mme|Don)\.?\s?)(\w+)'
# or keep both title and surname
pattern_with_title = r'((Dr|Mrs?|Ms|Miss|Master|Rev|Capt|Mlle|Col|Major|Sir|Lady|Mme|Don)\.?\s?)(\w+)'
#sample data
df = spark.createDataFrame([["Braund, Mr. Owen other stuff"],
["Cumings, Mrs. Joh some details"],
["Heikkinen, Miss. Hellen blah"],
["Futrelle, Mrs. Ja .... .... "]], ["Name"])
df.show()
+-----------------+
| Name|
+-----------------+
| Braund, Mr. Owen|
|Cumings, Mrs. Joh|
| Heikkinen, Miss.|
|Futrelle, Mrs. Ja|
+-----------------+
# create a column with what matches the pattern
df = df.withColumn("Surname", regexp_extract("Name", pattern, 1))
df.show()
# keeps only the Surname
+-----------------+---------+
| Name| Surname|
+-----------------+---------+
| Braund, Mr. Owen| Owen |
|Cumings, Mrs. Joh| Joh |
| Heikkinen, Miss.| Hellen |
|Futrelle, Mrs. Ja| Ja |
+-----------------+---------+
# in case you want both title and Surname:
df = df.withColumn("Surname with title", regexp_extract("Name", pattern_with_title, 1))
+-----------------+---------+--------------------+
| Name| Surname| Surname with title|
+-----------------+---------+--------------------+
|Braund, Mr. Owen | Owen | Mr. Ownen |
|Cumings, Mrs. Joh| Joh | Mrs. Joh |
|Heikkinen, Miss..| Hellen | Miss. Hellen |
|Futrelle, Mrs. Ja| Ja | Mrs. Ja |
+-----------------+---------+--------------------+
If you need the full Name, title Surname, then slightly change the pattern to include those too, e.g.:
main_pattern = r'Dr|Mrs?|Ms|Miss|Master|Rev|Capt|Mlle|Col|Major|Sir|Lady|Mme|Don'
pattern_full = r'(\w+,?\s('+ main_pattern+')\.?\s?\w+)'
pattern_name = r'(?:(?:'+ main_pattern+')\.?\s?)(\w+)'
pattern_title = r'(?:('+ main_pattern+')\.?\s?)'
pattern_surname = r'(\w+)(?:\,\s?(?:'+ main_pattern+')\.?\s?)'
df = df.withColumn("Full Name", regexp_extract("Name", pattern_full, 1))
df = df.withColumn("First Name", regexp_extract("Name", pattern_name, 1))
df = df.withColumn("Surname", regexp_extract("Name", pattern_surname, 1))
df = df.withColumn("Title", regexp_extract("Name", pattern_title, 1))
df.show(10, False)
+------------------------------+-----------------------+----------+------------+-----+
|Name |Full Name |Surname |First Name |Title|
+------------------------------+-----------------------+----------+------------+-----+
|Braund, Mr. Owen other stuff |Braund, Mr. Owen |Braund |Owen |Mr |
|Cumings, Mrs. Joh some details|Cumings, Mrs. Joh |Cumings |Joh |Mrs |
|Heikkinen, Miss. Hellen blah |Heikkinen, Miss. Hellen|Heikkinen |Hellen |Miss |
|Futrelle, Mrs. Ja .... .... |Futrelle, Mrs. Ja |Futrelle |Ja |Mrs |
+------------------------------+-----------------------+----------+------------+-----+
It is all about which part to ignore and which part to select in the regex. Hope this helps, good luck!
Note: not the optimal regex and it has room to improve.