嵌套列作为Spark中的行

时间:2017-03-16 06:26:00

标签: python apache-spark pyspark spark-dataframe udf

假设我有这个XML文件:

<root>
  <id>1</id>
  <tags>
    <tagA>
      <value>A1</value>
    </tagA>
    <tagA>
      <value>A2</value>
    </tagA>
    <tagB>
      <value>B</value>
    </tagB>
    <tagC>
      <value>C</value>
    </tagC>
  </tags>
</root>

我在python中使用spark-xml加载到Spark中,我得到了这个DataFrame:

+---+----------------------------------+
|id |tags                              |
+---+----------------------------------+
|1  |[WrappedArray([A1], [A2]),[B],[C]]|
+---+----------------------------------+

获得此期望输出的最佳方法是什么:

+---+-------+-----+
| id|tagName|value|
+---+-------+-----+
|  1|   tagA|   A1|
|  1|   tagA|   A2|
|  1|   tagB|    B|
|  1|   tagC|    C|
+---+-------+-----+

我提出的一个解决方案(尚未完成,未经测试,但应该工作)是使用python UDF获取tags列作为输入,并遍历每个标记并返回一个新列表:

def myf(tags):
    ....
    return [[1,'tagA','A1'],[1,'tagA','A2'],[1,'tagB','B'],[1,'tagC','C']]

我可以使用explode()为此数组中的每个条目创建单独的行。但是,为此我需要注册一个带有显式模式的UDF作为返回类型,例如

format = ArrayType(
                   StructType([
                               StructField('id',IntegerType()),
                               StructField('tagName',StringType()),
                               StructField('value',StringType())
                              ]
                  )
spark.udf.register('myf', myf, format)

然后使用它,例如:

df.selectExpr('explode(myf(tags)) AS cols').select('cols.id','cols.tagName','cols.value')

问题是,首先,我不确定这是否是最好的方法,更重要的是,性能,因为我将处理很多行。其次,我不想为函数返回对象定义静态模式,它需要尽可能动态。 有没有更好的方法来实现这一点,最好是使用UDF和DataFrame而不是RDD,并希望我不要求太多,可能在一个单一的查询运行中?

PS:最好保留tags下的标签顺序。

0 个答案:

没有答案