Как использовать на массиве - PullRequest
2 голосов
/ 14 октября 2019

У меня есть pyspark Dataframe, который содержит 4 столбца. Я хочу извлечь некоторую строку из одного столбца, это тип Array of strings. Я использовал функцию regexp_extract, но она вернула ошибку, потому что regexp_extract принимает только строки.

пример dataframe:

id |  last_name | age | Identificator
------------------------------------------------------------------
12 | AA         | 23  |  "[""AZE","POI","76759","T86420","ADAPT"]"
------------------------------------------------------------------
24 | BB         | 24  | "[""SDN","34","35","AZE","21054","20126"]"
------------------------------------------------------------------

Я хочу извлечь все числа, которые:

- contain 4, 5 or 6 digits
 - it should not attached to a letters.
 - if attached to letter Z ok, I should extract it.
 - save it in a new column in my Dataframe.

Я начал делать это так, но это не работает, потому что заголовок представляет собой массив строк.

expression = r'([0-9]){4,6}'
 df = df.withColumn("extract", F.regexp_extract(F.col("Identificator"), expression, 1))

Как я могу извлечь эти числа, используя regexp_extract или другое решение? Спасибо

1 Ответ

3 голосов
/ 14 октября 2019

Вот что я могу сделать, используя SparkSQL 2.4.0 + встроенная функция filter :

from pyspark.sql.functions import expr

df.withColumn('text_new', expr('filter(text, x -> x rlike "^Z?[0-9]{4,6}$")')) \
  .show(truncate=False)                                                                          
#+-----------------------------------+---------------------+
#|text                               |text_new             |
#+-----------------------------------+---------------------+
#|[AZE, POI, 76759, T86420, ADAPT]   |[76759]              |
#|[SDN, 34, Z8735, AZE, 21054, 20126]|[Z8735, 21054, 20126]|
#+-----------------------------------+---------------------+

В результате получается массив, содержащий совпадающие элементы. регулярное выражение ^Z?[0-9]{4,6}$ соответствует 4-6 цифрам, перед которыми необязательно предшествует символ 'Z'.

Редактировать: для более старой версии Apache Spark, используйте udf () :

import re
from pyspark.sql.functions import udf
from pyspark.sql.types import ArrayType, StringType

# regex pattern:
ptn = re.compile('^Z?[0-9]{4,6}$')

# create an udf to filter array
array_filter = udf(lambda arr: [ x for x in arr if re.match(ptn, x) ] if type(arr) is list else arr, ArrayType(StringType()))

df.withColumn('text_new', array_filter('text')) \
  .show(truncate=False)

Edit-2: на основе вашего комментария, от 'Z' до 'MOD' и удалите начальную MOD, используйте lstrip () для удаления этой подстроки. отрегулируйте следующее:

ptn = re.complie(r'^(?:MOD)?[0-9]{4,6}$')

array_filter = udf(lambda arr: [ x.lstrip('MOD') for x in arr if re.match(ptn, x) ] if type(arr) is list else arr, ArrayType(StringType()))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...