我的 DataFrame 具有以下结构:
-------------------------
| Brand | type | amount|
-------------------------
| B | a | 10 |
| B | b | 20 |
| C | c | 30 |
-------------------------
我想通过将type
和amount
分组到一个类型的列中来减少行数:Map
因此Brand
将是唯一的,MAP_type_AMOUNT
将key,value
type
amount
组合{/ 1}}。
我认为Spark.sql可能有一些功能可以帮助这个过程,或者我必须让RDD成为DataFrame并使我的"拥有"转换为地图类型?
预期:
-------------------------
| Brand | MAP_type_AMOUNT
-------------------------
| B | {a: 10, b:20} |
| C | {c: 30} |
-------------------------
答案 0 :(得分:7)
Prem's答案略有改进(抱歉,我无法发表评论)
使用func.create_map
代替func.struct
。见documentation
import pyspark.sql.functions as func
df = sc.parallelize([('B','a',10),('B','b',20),
('C','c',30)]).toDF(['Brand','Type','Amount'])
df_converted = df.groupBy("Brand").\
agg(func.collect_list(func.create_map(func.col("Type"),
func.col("Amount"))).alias("MAP_type_AMOUNT"))
print df_converted.collect()
输出:
[Row(Brand=u'B', MAP_type_AMOUNT=[{u'a': 10}, {u'b': 20}]),
Row(Brand=u'C', MAP_type_AMOUNT=[{u'c': 30}])]
答案 1 :(得分:5)
您可以拥有以下内容,但不完全是' Map'
import pyspark.sql.functions as func
df = sc.parallelize([('B','a',10),('B','b',20),('C','c',30)]).toDF(['Brand','Type','Amount'])
df_converted = df.groupBy("Brand").\
agg(func.collect_list(func.struct(func.col("Type"), func.col("Amount"))).alias("MAP_type_AMOUNT"))
df_converted.show()
输出是:
+-----+----------------+
|Brand| MAP_type_AMOUNT|
+-----+----------------+
| B|[[a,10], [b,20]]|
| C| [[c,30]]|
+-----+----------------+
希望这有帮助!
答案 2 :(得分:2)
同时使用collect_list
和map_from_arrays
可以实现这一目标
import pyspark.sql.functions as F
df_converted = (
df.groupBy('Brand')
.agg(
F.collect_list('type').alias('type'),
F.collect_list('amount').alias('amount'),
)
.withColumn('MAP_type_AMOUNT', F.map_from_arrays('type', 'amount'))
.drop('type', 'amount')
)
输出
+-----+------------------+
|Brand| MAP_type_AMOUNT|
+-----+------------------+
| C| [c -> 30]|
| B|[b -> 20, a -> 10]|
+-----+------------------+