Использование Spark для расширения строки JSON по строкам и столбцам - PullRequest
1 голос
/ 15 апреля 2020

Я новичок в Spark и работаю с JSON, и у меня возникают проблемы при выполнении чего-то довольно простого (я думаю). Я пытался использовать части решений для похожих вопросов, но не совсем понял это правильно. В настоящее время у меня есть фрейм данных Spark с несколькими столбцами, представляющими переменные. Каждая строка представляет собой уникальную комбинацию значений переменных. Затем у меня есть UDF, который применяется к каждой строке, которая принимает каждый из столбцов в качестве входных данных, выполняет некоторый анализ и выводит сводную таблицу в виде строки JSON для каждой строки, и сохраняет эти результаты в новом столбце Таблица. Некоторые небольшие примерные данные выглядят так:

+------+-----+------+-------------------------------------------------------------------
|Var 1 |Var 2|Var 3 |JSON Table 
+------+------------+-------------------------------------------------------------------
|True  |10%  |200   |[{"Out_1": "Mean", "Out_2": "25"}, {"Out_1": "Median", "Out_2": "21"}]
|False |15%  |150   |[{"Out_1": "Mean", "Out_2": "19"}, {"Out_1": "Median", "Out_2": "18"}]
|True  |12%  |100   |[{"Out_1": "Mean", "Out_2": "22"}, {"Out_1": "Median", "Out_2": "20"}]

Я хотел бы преобразовать это в следующий формат:

+------+-----+------+------+-----+
|Var 1 |Var 2|Var 3 |Out_1 |Out_2| 
+------+------------+------+-----+
|True  |10%  |200   |Mean  |25   |
|True  |10%  |200   |Median|21   |
|False |15%  |150   |Mean  |19   |
|False |15%  |150   |Median|18   |
|True  |12%  |100   |Mean  |22   |
|True  |12%  |100   |Median|20   |

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

from pyspark.sql.functions import *
from pyspark.sql.types import *

schema = spark.read.json(df.rdd.map(lambda row: row["JSON Table"])).schema

df = df\
     .withColumn("JSON Table", from_json("JSON Table", schema))\
     .select(col('*'), col('JSON Table.*'))\

df.show()

Это похоже на правильную структуру JSON (хотя каждое значение читается как строка, хотя большинство являются целыми числами), но результирующий кадр данных пуст, хотя и имеет правильные заголовки столбцов. Любой совет, как с этим бороться?

1 Ответ

0 голосов
/ 15 апреля 2020

Предполагая, что ваш столбец JSON table равен json string. Вы можете явно указать свои schema, explode(from_json), а затем select свои столбцы.

df.show() #sample dataframe
+-----+-----+-----+----------------------------------------------------------------------+
|Var 1|Var 2|Var 3|JSON Table                                                            |
+-----+-----+-----+----------------------------------------------------------------------+
|true |10%  |200  |[{"Out_1": "Mean", "Out_2": "25"}, {"Out_1": "Median", "Out_2": "21"}]|
|false|15%  |150  |[{"Out_1": "Mean", "Out_2": "19"}, {"Out_1": "Median", "Out_2": "18"}]|
|true |12%  |100  |[{"Out_1": "Mean", "Out_2": "22"}, {"Out_1": "Median", "Out_2": "20"}]|
+-----+-----+-----+----------------------------------------------------------------------+

#sample schema     
#root
 #|-- Var 1: boolean (nullable = true)
 #|-- Var 2: string (nullable = true)
 #|-- Var 3: long (nullable = true)
 #|-- JSON Table: string (nullable = true)


from pyspark.sql import functions as F
from pyspark.sql.types import *

schema = ArrayType(MapType(StringType(),StringType()))

df.withColumn("JSON Table", F.explode(F.from_json("JSON Table", schema)))\
  .select("Var 1","Var 2","Var 3","JSON Table.Out_1","JSON Table.Out_2").show()

+-----+-----+-----+------+-----+
|Var 1|Var 2|Var 3| Out_1|Out_2|
+-----+-----+-----+------+-----+
| true|  10%|  200|  Mean|   25|
| true|  10%|  200|Median|   21|
|false|  15%|  150|  Mean|   19|
|false|  15%|  150|Median|   18|
| true|  12%|  100|  Mean|   22|
| true|  12%|  100|Median|   20|
+-----+-----+-----+------+-----+
...