我有一个带有MapType
列的pyspark DataFrame,我想将其分解为所有列(按键的名称)
root
|-- a: map (nullable = true)
| |-- key: string
| |-- value: long (valueContainsNull = true)
我想做sp_test.select('a.*')
,但得到一个错误:
分析异常:'只能星星展开结构数据类型。属性:ArrayBuffer(a)
;'
如果我们知道所有的钥匙,这可以通过做来实现
sp_test.select(['a.%s'%item for item in ['a','b']]).show()
但我想删除关键依赖
如果我们有一个StructType列,这可以通过执行display(nested_df.select('*', 'nested_array.*'))
轻松实现
root
|-- _corrupt_record: string (nullable = true)
|-- field1: long (nullable = true)
|-- field2: long (nullable = true)
|-- nested_array: struct (nullable = true)
| |-- nested_field1: long (nullable = true)
| |-- nested_field2: long (nullable = true)
我有一些疑问:
MapType
可以转换为StructType
吗?
1.我们可以直接从MapType
查询子键吗?
1条答案
按热度按时间4nkexdtk1#
**TL;DR:**除非你提前知道可能的密钥,否则没有简单的方法来完成你的要求。
让我用一个例子来解释为什么和你的选择是什么。
首先,创建以下DataFrame:
它具有以下模式:
MapType
可以转换为StructType
吗?简单的答案是否定的(至少不是没有效率的),除非你提前知道钥匙。
MapType
和StructType
之间的区别在于Map的键值对是行独立的。StructType
列不是这样的-在结构体列中,所有行都有相同的结构体字段。由于这个原因,spark不能很容易地从map中推断出要创建哪些列。(记住spark是并行操作每一行的)另一方面,将结构体分解成列是很简单的,因为所有的列都是提前知道的。
所以如果你知道键,你可以通过以下方式创建一个结构类型:
新的schema是:
1.我们可以直接从MapType查询子键吗?
是的,(如上所示)你可以使用
getItem()
,它将从列表中的索引处获取一个项,或者从Map中通过键获取一个项。如果你不知道这些键,你唯一的选择就是将Map
explode
分成行groupby
和pivot
。在本例中,我们需要首先创建一个
id
列,以便有分组依据。这里的
pivot
可能很昂贵,具体取决于数据的大小。