Разделить текст в кадре данных и проверить, содержит ли подстрока - PullRequest
1 голос
/ 15 мая 2019

Итак, я хочу проверить, содержит ли мой текст слово «ребенок», а не любое другое слово, содержащее «ребенок». Например, «maybaby» не будет совпадением. У меня уже есть фрагмент кода, который работает, но я хотел посмотреть, есть ли лучший способ форматирования, чтобы мне не приходилось просматривать данные дважды. Вот что у меня есть:

import pyspark.sql.functions as F

rows = sc.parallelize([['14-banana'], ['12-cheese'], ['13-olives'], ['11-almonds'], ['23-maybaby'], ['54-baby']])

rows_df = rows.toDF(["ID"])
split = F.split(rows_df.ID, '-')

rows_df = rows_df.withColumn('fruit', split)

+----------+-------------+
|        ID|        fruit|
+----------+-------------+
| 14-banana| [14, banana]|
| 12-cheese| [12, cheese]|
| 13-olives| [13, olives]|
|11-almonds|[11, almonds]|
|23-maybaby|[23, maybaby]|
|   54-baby|   [54, baby]|
+----------+-------------+

from pyspark.sql.types import StringType
def func(col):
  for item in col:
    if item == "baby":
      return "yes"

  return "no"
func_udf = udf(func, StringType())
df_hierachy_concept = rows_df.withColumn('new',func_udf(rows_df['fruit']))

+----------+-------------+---+
|        ID|        fruit|new|
+----------+-------------+---+
| 14-banana| [14, banana]| no|
| 12-cheese| [12, cheese]| no|
| 13-olives| [13, olives]| no|
|11-almonds|[11, almonds]| no|
|23-maybaby|[23, maybaby]| no|
|   54-baby|   [54, baby]|yes|
+----------+-------------+---+

В конечном счете, я просто хочу только столбец "ID" и "новый".

Ответы [ 2 ]

2 голосов
/ 15 мая 2019

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

См. Примеры ниже:

from pyspark.shell import sc
from pyspark.sql.functions import split, when

rows = sc.parallelize(
    [
        ['14-banana'], ['12-cheese'], ['13-olives'], 
        ['11-almonds'], ['23-maybaby'], ['54-baby']
    ]
)

# Resolves with auxiliary column named "fruit"
rows_df = rows.toDF(["ID"])
rows_df = rows_df.withColumn('fruit', split(rows_df.ID, '-')[1])

rows_df = rows_df.withColumn('new', when(rows_df.fruit == 'baby', 'yes').otherwise('no'))
rows_df = rows_df.drop('fruit')
rows_df.show()

# Resolves directly without creating an auxiliary column
rows_df = rows.toDF(["ID"])
rows_df = rows_df.withColumn(
    'new',
     when(split(rows_df.ID, '-')[1] == 'baby', 'yes').otherwise('no')
)
rows_df.show()

# Resolves without forcing `split()[1]` call, avoiding out of index exception
rows_df = rows.toDF(["ID"])
is_new_udf = udf(lambda col: 'yes' if any(value == 'baby' for value in col) else 'no')
rows_df = rows_df.withColumn('new', is_new_udf(split(rows_df.ID, '-')))
rows_df.show()

Все выходы одинаковы:

+----------+---+
|        ID|new|
+----------+---+
| 14-banana| no|
| 12-cheese| no|
| 13-olives| no|
|11-almonds| no|
|23-maybaby| no|
|   54-baby|yes|
+----------+---+
1 голос
/ 16 мая 2019

Я бы использовал для этого pyspark.sql.functions.regexp_extract.Сделайте столбец new равным "yes", если вы можете извлечь слово "baby" с границей слова с обеих сторон, и "no" в противном случае.

from pyspark.sql.functions import regexp_extract, when
rows_df.withColumn(
    'new',
    when(
        regexp_extract("ID", "(?<=(\b|\-))baby(?=(\b|$))", 0) == "baby",
        "yes"
    ).otherwise("no")
).show()
#+----------+-------------+---+
#|        ID|        fruit|new|
#+----------+-------------+---+
#| 14-banana| [14, banana]| no|
#| 12-cheese| [12, cheese]| no|
#| 13-olives| [13, olives]| no|
#|11-almonds|[11, almonds]| no|
#|23-maybaby|[23, maybaby]| no|
#|   54-baby|   [54, baby]|yes|
#+----------+-------------+---+

Последний аргументregexp_extract - индекс соответствия для извлечения.Выбираем первый индекс (индекс 0).Если шаблон не совпадает, возвращается пустая строка.Наконец, используйте when(), чтобы проверить, равна ли извлеченная строка желаемому значению.

Шаблон регулярного выражения означает:

  • (?<=(\b|\-)): положительный просмотрдля границы слова (\b) или буквального дефиса (-).
  • baby: буквенное слово "baby"
  • (?=(\b|$)): положительный прогноздля границы слова или конца строки ($).

Этот метод также не требует, чтобы вы сначала разбили строку, потому что неясно, нужна ли эта часть для вашегоцели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...