在Pyspark df中将字典键添加为列名,将字典值添加为该列的常量值

在Pyspark df中将字典键添加为列名,将字典值添加为该列的常量值,pyspark,apache-spark-sql,pyspark-sql,Pyspark,Apache Spark Sql,Pyspark Sql,我有一本字典x={'colA':20,'colB':30}和一本pyspark df ID Value 1 ABC 1 BCD 1 AKB 2 CAB 2 AIK 3 KIB 我希望使用x创建df1,如下所示: ID Value colA colB 1 ABC 20.0 30.0 1 BCD 20.0 30.0 1 AKB 20.0 30.0 2 CAB 20.0 30.0 ... 你知道怎么做吗。 我知道我可以创建这样的常量列 df1

我有一本字典x={'colA':20,'colB':30}和一本pyspark df

ID Value
1  ABC
1  BCD
1  AKB
2  CAB
2  AIK
3  KIB 
我希望使用x创建df1,如下所示:

ID Value colA colB
1  ABC    20.0  30.0
1  BCD    20.0  30.0
1  AKB    20.0  30.0
2  CAB    20.0  30.0
...
你知道怎么做吗。 我知道我可以创建这样的常量列

df1 = df.withColumn('colA', lit(20.0))
df1 = df1.withColumn('colB', lit(30.0))

但不确定从dictionary循环执行该操作的动态过程,如下所示

df1 = df  
for key in x:
    df1 = df1.withColumn(key, lit(x[key]))
有很多方法可以隐藏循环,但执行过程是相同的。例如,您可以使用选择:

从pyspark.sql.functions导入 df2=df.选择*,*[litval.aliaskey代表键,val代表x.items] df2.show +--+---+--+--+ |ID | Value | colB | colA| +--+---+--+--+ |1 | ABC | 30 | 20| |1 | BCD | 30 | 20| |1 | AKB | 30 | 20| |2 |驾驶室| 30 | 20| |2 | AIK | 30 | 20| |3 | KIB | 30 | 20| +--+---+--+--+ 或functools.reduce和with列:

从functools导入reduce df3=reducelambda-df,key:df.withColumnkey,litx[key],x,df df3.show 同上 或与:

从pyspark.sql.functions导入结构 df4=df.withColumn'x',struct[litval.aliaskey表示键,val表示x.items]\ .selectID,Value,x* df4.show 同上 但如果您查看这些方法的执行计划,就会发现它们完全相同:

解释 ==实际计划== *项目[ID44L,值45,30为colB151,20为colA152] +-扫描现有RDD[ID44L,值45] 解释 ==实际计划== *项目[ID44L,值45,30为colB102,20为colA107] +-扫描现有RDD[ID44L,值45] 解释 ==实际计划== *项目[ID44L,值45,30为colB120,20为colA121] +-扫描现有RDD[ID44L,值45] 此外,如果您比较@anil中的循环方法:

df1=df 对于输入x: df1=df1.withColumnkey,litx[key] 解释 ==实际计划== *项目[ID44L,值45,30为colB127,20为colA132] +-扫描现有RDD[ID44L,值45]
你会发现这也是一样的。

谢谢。有没有办法将所有键应用到一起,一次创建所有列而不经过循环?即使在循环中应用它,spark也只会执行一次,因为它是一个懒惰的计算。。。你不必担心性能。好的。知道了。我也找到了这个解决方案,但我认为它效率低下。这就是为什么我问你。非常感谢你的帮助。我有一个类似的问题,@pault