#python #regex #apache-spark #pyspark #mapping
Вопрос:
У меня есть фрейм данных PySpark, похожий на этот:
A | B |
---|---|
1 | значение abc_value |
2 | значение abc_value |
3 | какое-то другое значение |
4 | anything_else |
У меня есть картографический словарь:
d = {
"abc":"X",
"some_other":Y,
"anything":Z
}
Мне нужно создать новый столбец в моем исходном фрейме данных, который должен быть таким:
A | B | C |
---|---|---|
1 | значение abc_value | X |
2 | значение abc_value | X |
3 | какое-то другое значение | Y |
4 | anything_else | Z |
Я попробовал составить карту так:
mapping_expr = f.create_map([f.lit(x) for x in chain(*d.items())])
а затем примените его, withColumn
однако это точное соответствие, однако мне нужно частичное (регулярное выражение), как вы можете видеть.
Как это сделать, пожалуйста?
Ответ №1:
Я боюсь, что в PySpark нет реализованной функции, которая извлекает подстроки в соответствии с определенным словарем; вам, вероятно, придется прибегнуть к трюкам.
В этом случае вы можете сначала создать строку поиска, которая включает в себя все ключи вашего словаря для поиска:
keys = list(d.keys())
keys_expr = '|'.join(keys)
keys_expr
# 'abc|some_other|anything'
Затем вы можете использовать regexp_extract
для извлечения первый ключ из keys_expr
того , с которым мы сталкиваемся в столбце B
, если он присутствует (в этом причина |
оператора).
Наконец, вы можете использовать словарь d
для замены значений в новом столбце.
import pyspark.sql.functions as F
df = df
.withColumn('C', F.regexp_extract('B', keys_expr, 0))
.replace(d, subset=['C'])
df.show()
--- ---------------- ---
| A| B| C|
--- ---------------- ---
| 1| abc_value| X|
| 2| abc_value| X|
| 3|some_other_value| Y|
| 4| anything_else| Z|
--- ---------------- ---