#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. Я проверил свой набор данных, есть только одно среднее имя, если есть среднее имя. Я попробовал ваш метод, он работает как шарм, спасибо.