如何为元组列表创建PySpark模式?

时间:2019-03-03 10:10:45

标签: apache-spark pyspark schema

以下元组列表的正确 PySpark 模式应该是什么?我想将架构应用于以下数据:

[('a', 0.0), ('b', 6), ('c', 44), ('d', 107), ('e', 0), ('f', 3), ('g', 4), ('h', 0.025599999353289604), ('i', 0.03239999711513519), ('j', -0.03205680847167969), ('k', 0.10429033637046814), ('l', (34.190006256103516, 31.09000015258789, 31.099994659423828)), ('m', (-9.32000732421875, -9.32000732421875, -11.610000610351562)) ]

我希望结果采用以下格式: Format

2 个答案:

答案 0 :(得分:1)

在使Spark等效之前,亲自描述元组会有所帮助。在Python中,似乎您有一个包含2个元素的元组。第一个是String,第二个是由3个Double值组成的另一个元组。前几项不一定符合此要求,但您不能期望有一个“动态”模式,但看起来至少第二个元组中的String和第一个数字始终存在。无论如何,表示这种数据类型的一种方法如下: (String, (Double, Double, Double))

与此相对应的Pyspark模式为:

from pyspark.sql.types import StructType, StructField, StringType, DoubleType

schema = StructType([
    StructField('char', StringType(), nullable=False),
    StructType([
        StructField('num_1', DoubleType, nullable=False),
        StructField('num_2', DoubleType, nullable=True),
        StructField('num_3', DoubleType, nullable=True),
    ])
])

答案 1 :(得分:1)

尽管我想提出另一种方法,但天津的答案应该可行。无需找出应该添加到架构中的列数来创建array / list类型的列。接下来的代码将您的数据转换为rdd,而不是元组包含[key,value]的行,其中value是双精度的列表。然后,您可以轻松地应用以下架构。

for key in dict.keys():
    print(key)

请注意,to_float_list函数接受一个元组或一个数字,并将其转换为一个double列表。这将输出:

def test():
    l = [('a', 0.0), 
    ('b', 6), 
    ('c', 44), 
    ('d', 107), 
    ('e', 0), 
    ('f', 3), 
    ('g', 4), 
    ('h', 0.025599999353289604), 
    ('i', 0.03239999711513519), 
    ('j', -0.03205680847167969), 
    ('k',0.10429033637046814), 
    ('l',(34.190006256103516, 31.09000015258789, 31.099994659423828)), 
    ('m',(-9.32000732421875, -9.32000732421875, -11.610000610351562))]

    # this schema should work for all your cases 
    schema = StructType([
        StructField("id", StringType(), False),
        StructField("num_list", ArrayType(DoubleType(), True), True)
    ])

    rdd = spark.sparkContext.parallelize(l).map(lambda r: (r[0], to_float_list(r[1])))

    df = spark.createDataFrame(rdd, schema)

    df.show(100, False)

def to_float_list(value):
    if type(value) is tuple:  
        return list(map(float, value))

    return [float(value)]