Как удалить NULL из структурного поля в pyspark? - PullRequest
0 голосов
/ 09 марта 2020

У меня есть DataFrame, который содержит одно поле структуры. Я хочу удалить значения, которые являются нулевыми, из поля структуры.

temp_df_struct = Df.withColumn("VIN_COUNTRY_CD",struct('BXSR_VEHICLE_1_VIN_COUNTRY_CD','BXSR_VEHICLE_2_VIN_COUNTRY_CD','BXSR_VEHICLE_3_VIN_COUNTRY_CD','BXSR_VEHICLE_4_VIN_COUNTRY_CD','BXSR_VEHICLE_5_VIN_COUNTRY_CD'))

В этих различных столбцах некоторые содержат значения NULL. Есть ли способ удалить ноль из поля структуры?

1 Ответ

0 голосов
/ 09 марта 2020

Вы всегда должны предоставлять небольшой воспроизводимый пример - но вот мое предположение относительно того, что вы хотите

Пример данных

data = [("1", "10", "20", None, "30", "40"), ("2", None, "15", "25", "35", None)]
names_of_cols = [
    "id",
    "BXSR_VEHICLE_1_VIN_COUNTRY_CD",
    "BXSR_VEHICLE_2_VIN_COUNTRY_CD",
    "BXSR_VEHICLE_3_VIN_COUNTRY_CD",
    "BXSR_VEHICLE_4_VIN_COUNTRY_CD",
    "BXSR_VEHICLE_5_VIN_COUNTRY_CD",
]
df = spark.createDataFrame(data, names_of_cols)
df.show(truncate=False)
# +---+-----------------------------+-----------------------------+-----------------------------+-----------------------------+-----------------------------+
# | id|BXSR_VEHICLE_1_VIN_COUNTRY_CD|BXSR_VEHICLE_2_VIN_COUNTRY_CD|BXSR_VEHICLE_3_VIN_COUNTRY_CD|BXSR_VEHICLE_4_VIN_COUNTRY_CD|BXSR_VEHICLE_5_VIN_COUNTRY_CD|
# +---+-----------------------------+-----------------------------+-----------------------------+-----------------------------+-----------------------------+
# |  1|                           10|                           20|                         null|                           30|                           40|
# |  2|                         null|                           15|                           25|                           35|                         null|
# +---+-----------------------------+-----------------------------+-----------------------------+-----------------------------+-----------------------------+

Воспроизведение того, что у вас есть

Вы хотите собирать значения из нескольких столбцов в массив, например

import re
from pyspark.sql.functions import col, array
collect_cols = [c for c in df.columns if re.match('BXSR_VEHICLE_\\d_VIN_COUNTRY_CD', c)]
collect_cols
# ['BXSR_VEHICLE_1_VIN_COUNTRY_CD', 'BXSR_VEHICLE_2_VIN_COUNTRY_CD', 'BXSR_VEHICLE_3_VIN_COUNTRY_CD', 'BXSR_VEHICLE_4_VIN_COUNTRY_CD', 'BXSR_VEHICLE_5_VIN_COUNTRY_CD']
(
    df.
        withColumn(
            "VIN_COUNTRY_CD",
            array(*collect_cols)
        ).
        select('id', 'VIN_COUNTRY_CD').
        show(truncate=False)
)
# +---+-----------------+
# |id |VIN_COUNTRY_CD   |
# +---+-----------------+
# |1  |[10, 20,, 30, 40]|
# |2  |[, 15, 25, 35,]  |
# +---+-----------------+

Solution

, а затем удалять значения NULL из массива

from pyspark.sql.functions import array, struct, lit, array_except
(
    df.
        withColumn(
            "VIN_COUNTRY_CD",
            array(*collect_cols)
        ).
        withColumn(
            'VIN_COUNTRY_CD',
            array_except(
                col('VIN_COUNTRY_CD'),
                array(lit(None).cast('string'))
            )
        ).
        select('id', 'VIN_COUNTRY_CD').
        show(truncate=False)
)
# +---+----------------+                                                          
# |id |VIN_COUNTRY_CD  |
# +---+----------------+
# |1  |[10, 20, 30, 40]|
# |2  |[15, 25, 35]    |
# +---+----------------+
...