假设我有这个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
下的标签顺序。