我目前正在尝试对服务列进行一些聚合。我想对所有类似的服务进行分组并对值进行求和,如果可能的话,将其展平为一行。
输入:
+------------------+--------------------+
| cid | Services|
+------------------+--------------------+
|845124826013182686| [112931, serv1]|
|845124826013182686| [146936, serv1]|
|845124826013182686| [32718, serv2]|
|845124826013182686| [28839, serv2]|
|845124826013182686| [8710, serv2]|
|845124826013182686| [2093140, serv3]|
希望输出:
+------------------+--------------------+------------------+--------------------+
| cid | serv1 | serv2 | serv3 |
+------------------+--------------------+------------------+--------------------+
|845124826013182686| 259867 | 70267 | 2093140 |
以下是我目前的代码
from pyspark.sql import SparkSession, functions
spark = SparkSession.builder.appName("Service Aggregation").getOrCreate()
pathToFile = '/path/to/jsonfile'
df = spark.read.json(pathToFile)
df2 = df.select('cid',functions.explode_outer(df.nodes.services))
finaldataFrame = df2.select('cid',(functions.explode_outer(df2.col)).alias('Services'))
finaldataFrame.show()
我对pyspark很新,并且一直在寻找资源并尝试创建一些UDF来应用于该列,但是带有ipyspark的map函数仅适用于RDD而不是DataFrames,并且我不确定如何向前移动以获得所需的输出
非常感谢任何建议或帮助。
printSchema的结果
root
|-- clusterId: string (nullable = true)
|-- col: array (nullable = true)
| |-- element: struct (containsNull = true)
| | |-- cpuCoreInSeconds: long (nullable = true)
| | |-- name: string (nullable = true)
答案 0 :(得分:2)
首先,按位置从Services
列中提取服务和值。请注意,这假设值始终位于位置0,服务始终位于位置1(如示例所示)。
import pyspark.sql.functions as f
df2 = df.select(
'cid',
f.col("Services").getItem(0).alias('value').cast('integer'),
f.col("Services").getItem(1).alias('service')
)
df2.show()
#+------------------+-------+-------+
#| cid| value|service|
#+------------------+-------+-------+
#|845124826013182686| 112931| serv1|
#|845124826013182686| 146936| serv1|
#|845124826013182686| 32718| serv2|
#|845124826013182686| 28839| serv2|
#|845124826013182686| 8710| serv2|
#|845124826013182686|2093140| serv3|
#+------------------+-------+-------+
请注意,我将value
转换为integer
,但它可能已经是一个整数,具体取决于您的架构的定义方式。
一旦数据采用这种格式,就很容易pivot()
。按cid
列分组,转动service
列,并通过汇总value
列进行汇总:
df2.groupBy('cid').pivot('service').sum("value").show()
#+------------------+------+-----+-------+
#| cid| serv1|serv2| serv3|
#+------------------+------+-----+-------+
#|845124826013182686|259867|70267|2093140|
#+------------------+------+-----+-------+
<强>更新强>
根据您提供的架构,您必须按名称而不是按位置获取价值和服务:
df2 = df.select(
'cid',
f.col("Services").getItem("cpuCoreInSeconds").alias('value'),
f.col("Services").getItem("name").alias('service')
)
其余的都是一样的。此外,无需转换为整数,因为cpuCoreInSeconds
已经是long
。