Я использую API отчетов администратора Google через Python SDK в Databricks (Spark + Python 3.5).
Возвращает данные в следующем формате (код pyspark Databricks):
dbutils.fs.put("/tmp/test.json", '''{
"userEmail": "rod@test.com",
"parameters": [
{
"intValue": "0",
"name": "classroom:num_courses_created"
},
{
"boolValue": true,
"name": "accounts:is_disabled"
},
{
"name": "classroom:role",
"stringValue": "student"
}
]
}''', True)
Есть 188 параметров, и для каждого параметра это может быть int, bool, date или string.В зависимости от типа поля Api возвращает значение в соответствующем значении (например, intValue для поля int и boolValue для логического значения).
Я записываю этот JSON нетронутым в мой набор данных и обрабатываю его позже, загружаяэто в искровой фрейм данных:
testJsonData = sqlContext.read.json("/tmp/test.json", multiLine=True)
В результате получается фрейм данных с такой схемой:
- userEmail: строка
- параметры: массив
- element: struct
- boolValue: логическое значение
- intValue: строка
- имя: строка
- stringValue: строка
Если я отображаю кадр данных, он отображается как
{"boolValue": null, "intValue": "0", "name": "classroom: num_courses_created","stringValue": null} {"boolValue": true, "intValue": null, "name": "accounts: is_disabled", "stringValue": null}
{"boolValue": null, "intValue": null, "name": "classroom: role", "stringValue": "student"}
Как вы можете видеть, он имеет нулевые значения для несуществующих типов.
Конечное состояние, которое мне нужно, - это столбцы в кадре данных, например:
, и поворотные столбцы будут напечатаны правильно (например, classroom: num_courses_created будеттипа int - см. желтые столбцы выше)
Вот что я пробовал до сих пор:
from pyspark.sql.functions import explode
tempDf = testJsonData.select("userEmail", explode("parameters").alias("parameters_exploded"))
explodedColsDf = tempDf.select("userEmail", "parameters_exploded.*")
Это приводит к кадру данных с этой схемой:
- userEmail: строка
- boolValue: логическое значение
- intValue: строка
- имя: строка
- stringValue: строка
Iзатем переведите строки в столбцы на основе поля «Имя» («classroom: num_courses_created», «classroom: role» и т. д. (существует 188 пар параметров имя / значение):
#turn intValue into an Int column
explodedColsDf = explodedColsDf.withColumn("intValue", explodedColsDf.intValue.cast(IntegerType()))
pivotedDf = explodedColsDf.groupBy("userEmail").pivot("name").sum("intValue")
, что приводит кэтот фрейм данных:
- userEmail: строка
- account: is_disabled: long
- classroom: num_courses_created: long
- classroom: роль: long
, что неверно, так как типы столбцов неверны.
Что мне нужно сделать, это somehow посмотреть на все typeValues для столбца параметра (нет способа узнать тип по имени или вывести его - кроме как в оригинальном Json, где он возвращает только значение typeValue, которое уместно), и все, что не равно NULL, являетсятип этого столбца.Каждый параметр появляется только один раз, поэтому для ключа электронной почты просто необходимо вывести значения строки, bool, int и date, а не агрегировать их.
Насколько мне известно, я подумал, что более простым решением может бытьвернитесь назад к началу и поверните столбцы за до Я выписываю Json, чтобы он был в том формате, который я хочу, когда я загружаю его обратно в Spark, однако я не хотел преобразовывать необработанные данныесовсем.Я также предпочел бы не кодировать схему для 188 полей вручную, так как я хочу динамически выбирать, какие поля мне нужны, поэтому он должен иметь возможность обрабатывать это.