Выполните цикл через фрейм данных pyspark один раз, чтобы найти строки, содержащие список значений

#pyspark

Вопрос:

У меня есть фрейм данных, аналогичный приведенному ниже в pyspark

Имя проекта Номер проекта
ТБД Канада 10000000000029
TBD Китай 10000000000033
TBD Соединенные Штаты 10000000000974
Американский дайвер 10000000000234
Цветок 2.0 10000000023947

Мне нужно извлечь страну из имени проекта, содержащего TBD. У меня также есть список названий стран из моей таблицы измерений country_list = ['Canada','United States',....., 'China'] , в этом списке около 75 стран

Сначала я попытался решить эту проблему с помощью цикла for, я написал следующее

 country_list = ['Canada','United States',....., 'China']
# Set initial ExtractCountry column
df = df.withColumn("ExtractColumn", lit(None).cast("string"))
# Loop through data frame
for country in country_list:
    df = df.withColumn("ExtractColumn", when(df.ProjectName.contains("TBD") 
                                             amp; df.ProjectName.contains(country), lit(country))
                                       .otherwise(F.col("ExtractColumn")))
 

Это работает, но для запуска требуется очень много времени, так как мой df такой большой, и это означает, что он имеет длину фрейма данных x 75 стран. Я знаю, что в pyspark нет индексации, такой как фрейм данных pandas (я должен использовать pyspark, не могу использовать панд), но в любом случае есть ли для меня возможность просматривать фрейм данных только один раз или каким-то другим способом сократить время выполнения?

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

1. Вам нужно распределить работу. Поместите country_list фрейм данных с одним столбцом страна. Затем присоединяйтесь/объединяйтесь/объединяйтесь с df , что приведет к масштабированию там, где цикл for этого не делает.

Ответ №1:

Вы можете просто удалить TBD из projectname с regexp_replace

 from pyspark.sql import functions as F

(df
    .withColumn('ExtractColumn', F
        .when(F.col('projectname').startswith('TBD'), F.regexp_replace('projectname', 'TBD ', ''))
    )
    .show(10, False)
)

# Output
#  ------------------ -------------- -------------- 
# |projectname       |projectnumber |ExtractColumn |
#  ------------------ -------------- -------------- 
# |TBD Canada        |10000000000029|Canada        |
# |TBD China         |10000000000033|China         |
# |TBD United Kingdom|10000000000033|United Kingdom|
# |US Diver          |10000000000234|null          |
# |Flower 2.0        |10000000023947|null          |
#  ------------------ -------------- -------------- 
 

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

1. как насчет того, когда название страны состоит из более чем одного слова? есть ли способ принять все значения разделения, кроме TBD?

2. Я на самом деле думал, что разделение может быть не очень хорошей идеей, вместо этого обновил свой ответ regex_replace .

3. не знал об этой функции. Спасибо! спаситель жизни

4. кроме того, я обновил ссылку на документ, там есть еще много функций, которые вы можете прочитать. Кроме того, не стесняйтесь принимать ответ, если вы нашли его полезным 🙂