Spark SQL - неверная структурная схема createDataFrame - PullRequest
0 голосов
/ 20 ноября 2018

При попытке создать DataFrame с помощью Spark SQL, передав ему список строк, например, так:

some_data = [{'some-column': [{'timestamp': 1353534535353, 'strVal': 'some-string'}]},
             {'some-column': [{'timestamp': 1353534535354, 'strVal': 'another-string'}]}]
spark.createDataFrame([Row(**d) for d in some_data]).printSchema()

Полученная схема DataFrame выглядит так:

root
 |--  some-column: array (nullable = true)
 |    |-- element: map (containsNull = true)
 |    |    |-- key: string
 |    |    |-- value: long (valueContainsNull = true)

Эта схема неверна, поскольку столбец strVal имеет тип string (и, действительно, сбор данных в этом DataFrame приведет к nulls в этом столбце).

Я ожидаю, что схема будет иметь значение Arrayподходящее Structs - выводится с небольшим количеством размышлений Python о типах значений.Почему это не так?Могу ли я что-нибудь сделать, кроме явного указания схемы в этом случае?

1 Ответ

0 голосов
/ 20 ноября 2018

Это происходит потому, что структура не кодирует то, что вы имеете в виду.Как объясняется в руководстве по SQL * Python dict отображается на MapType.

Для работы со структурами следует использовать вложенные Rows (namedtuples предпочтительнее вобщие, но требующие действительные идентификаторы имени ):

from pyspark.sql import Row

Outer = Row("some-column")
Inner = Row("timestamp", "strVal")

spark.createDataFrame([
    Outer([Inner(1353534535353, 'some-string')]),
    Outer([Inner(1353534535354, 'another-string')])
]).printSchema()
root
 |-- some-column: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- timestamp: long (nullable = true)
 |    |    |-- strVal: string (nullable = true)

С имеющейся у вас структурой результат схемы может быть достигнут с промежуточным JSON:

import json

spark.read.json(sc.parallelize(some_data).map(json.dumps)).printSchema()
root
 |-- some-column: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- strVal: string (nullable = true)
 |    |    |-- timestamp: long (nullable = true)

или явная схема:

from pyspark.sql.types import *

schema = StructType([StructField(
    "some-column", ArrayType(StructType([
        StructField("timestamp", LongType()), 
        StructField("strVal", StringType())])
))])

spark.createDataFrame(some_data, schema)

, хотя последний метод может быть не совсем устойчивым.

...