Ваши строки:
"{color: red, car: volkswagen}"
"{color: blue, car: mazda}"
не в дружественном для Python формате. Они не могут быть проанализированы с помощью json.loads
, а также не могут быть оценены с помощью ast.literal_eval
.
Однако, если вы знали ключи заранее и можете предполагать, что строки всегда в этом формате, вы должны использовать pyspark.sql.functions.regexp_extract
:
Например:
from pyspark.sql.functions import regexp_extract
df.withColumn("color", regexp_extract("info", "(?<=color: )\w+(?=(,|}))", 0))\
.withColumn("car", regexp_extract("info", "(?<=car: )\w+(?=(,|}))", 0))\
.show(truncate=False)
#+----+---+-----------------------------+-----+----------+
#|name|age|info |color|car |
#+----+---+-----------------------------+-----+----------+
#|rob |26 |{color: red, car: volkswagen}|red |volkswagen|
#|evan|25 |{color: blue, car: mazda} |blue |mazda |
#+----+---+-----------------------------+-----+----------+
Узор:
(?<=color: )
: положительный взгляд на буквальную строку "color: "
\w+
: один или несколько символов слова
(?=(,|}))
: положительный прогноз для буквальной запятой или закрытой фигурной скобки.
Вот как можно обобщить это для более чем двух ключей и обработать случай, когда ключ не существует в строке.
from pyspark.sql.functions import regexp_extract, when, col
from functools import reduce
keys = ["color", "car", "year"]
pat = "(?<=%s: )\w+(?=(,|}))"
df = reduce(
lambda df, c: df.withColumn(
c,
when(
col("info").rlike(pat%c),
regexp_extract("info", pat%c, 0)
)
),
keys,
df
)
df.drop("info").show(truncate=False)
#+----+---+-----+----------+----+
#|name|age|color|car |year|
#+----+---+-----+----------+----+
#|rob |26 |red |volkswagen|null|
#|evan|25 |blue |mazda |null|
#+----+---+-----+----------+----+
В этом случае мы используем pyspark.sql.functions.when
и pyspark.sql.Column.rlike
, чтобы проверить, содержит ли строка шаблон, прежде чем пытаться извлечь совпадение.
Если вы не знаете ключей заранее, вам придется написать собственный синтаксический анализатор или попытаться изменить данные в восходящем потоке.