Разбить столбец с именем фрейма данных Spark на три столбца

#dataframe #pyspark #split

#фрейм данных #pyspark #разделить

Вопрос:

У меня есть фрейм данных в Spark, столбец — это имя, это строка, разделенная пробелом, сложность в том, что у некоторых имен есть второе имя, у других нет. Как я могу разделить столбец на firstname, middlename и lastname? Я использую F.split, не знаю, как отличить второе имя и фамилию. Я понимаю, что не могу использовать отрицательный индекс в Spark. Взгляните на мой пример df

 from pyspark.sql import functions as F
cols = ['id', 'name']
vals = [('l03', 'Bob K Barry'), ('S20', 'Cindy Winston'), ('l10', 'Jerry Kyle Moore'), ('j31', 'Dora Larson')]
df = spark.createDataFrame(vals, cols)
df.show()
 --- ----------------                                                           
| id|            name|
 --- ---------------- 
|l03|     Bob K Barry|
|S20|   Cindy Winston|
|l10|Jerry Kyle Moore|
|j31|     Dora Larson|
 --- ---------------- 


split_col = F.split(df['name'], ' ')
df = df.withColumn('firstname', split_col.getItem(0))
df.show()
 --- ---------------- ---------                                                 
| id|            name|firstname|
 --- ---------------- --------- 
|l03|     Bob K Barry|      Bob|
|S20|   Cindy Winston|    Cindy|
|l10|Jerry Kyle Moore|    Jerry|
|j31|     Dora Larson|     Dora|
 --- ---------------- --------- 
  

Как мне продолжить разделение? Приветствуется.

Ответ №1:

Первый элемент в массиве всегда должен быть как the firstname , а последний элемент — как lastname (using size ). Если не может быть более 1 среднего имени, вы можете сделать:

 from pyspark.sql import functions as F
from pyspark.sql.functions import *

df.withColumn("split_list", F.split(F.col("name"), " ")).withColumn("fn", col("split_list")[0])
    .withColumn("ln", col("split_list")[F.size("split_list") - 1])
    .withColumn("mn", when(F.size("split_list")==2, None)
    .otherwise(col("split_list")[1])).drop("split_list").show()
 --- ---------------- ----- ------- ---- 
| id|            name|   fn|     ln|  mn|
 --- ---------------- ----- ------- ---- 
|l03|     Bob K Barry|  Bob|  Barry|   K|
|S20|   Cindy Winston|Cindy|Winston|null|
|l10|Jerry Kyle Moore|Jerry|  Moore|Kyle|
|j31|     Dora Larson| Dora| Larson|null|
 --- ---------------- ----- ------- ---- 
  

Если может быть более 1 среднего имени, то вы можете использовать substring name middlename столбец on for:

 df.withColumn("split_list", F.split(F.col("name"), " ")).withColumn("fn", col("split_list")[0])
    .withColumn("ln", col("split_list")[F.size("split_list") - 1])
    .withColumn("mn", when(F.size("split_list")==2, None)
    .otherwise(col('name').substr(F.length("fn") 2, 
    F.length("name")-F.length("fn")-F.length("ln")-2))).drop("split_list").show()
 --- ---------------- ----- ------- ----- 
| id|            name|   fn|     ln|   mn|
 --- ---------------- ----- ------- ----- 
|l03|     Bob K Barry|  Bob|  Barry|    K|
|S20|   Cindy Winston|Cindy|Winston| null|
|l10|Jerry Kyle Moore|Jerry|  Moore| Kyle|
|j31|     Dora Larson| Dora| Larson| null|
|A12|     Fn A B C Ln|   Fn|     Ln|A B C|
 --- ---------------- ----- ------- ----- 
  

Я предполагаю, что FN является первым элементом, а LN — последним элементом, а все, что находится между ними, — это MN. Это не всегда верно, поскольку у людей может быть несколько FN / LN.

Комментарии:

1. Я проверил свой набор данных, есть только одно среднее имя, если есть среднее имя. Я попробовал ваш метод, он работает как шарм, спасибо.