使用Pyspark将不同的行值转换为具有相应行的不同列
我是Pyspark的新手,正在尝试转换数据 给定数据帧使用Pyspark将不同的行值转换为具有相应行的不同列,pyspark,pivot,rdd,transpose,flatmap,Pyspark,Pivot,Rdd,Transpose,Flatmap,我是Pyspark的新手,正在尝试转换数据 给定数据帧 Col1 A=id1a A=id2a B=id1b C=id1c B=id2b D=id1d A=id3a B=id3b C=id2c A=id4a C=id3c 所需: A B C id1a id1b id1c id2a id2b id2c id3a id3b id3b id4a null null 我尝试过pivot,但它给出了第一个值。可
Col1
A=id1a A=id2a B=id1b C=id1c B=id2b
D=id1d A=id3a B=id3b C=id2c
A=id4a C=id3c
所需:
A B C
id1a id1b id1c
id2a id2b id2c
id3a id3b id3b
id4a null null
我尝试过pivot,但它给出了第一个值。可能是因为我不知道全部情况,但数据格式似乎很奇怪。如果无法在数据源上执行任何操作,则需要进行一些收集、数据透视和连接。试试这个
import pyspark.sql.functions as F
test = sqlContext.createDataFrame([('A=id1a A=id2a B=id1b C=id1c B=id2b',1),('D=id1d A=id3a B=id3b C=id2c',2),('A=id4a C=id3c',3)],schema=['col1','id'])
tst_spl = test.withColumn("item",(F.split('col1'," ")))
tst_xpl = tst_spl.select(F.explode("item"))
tst_map = tst_xpl.withColumn("key",F.split('col','=')[0]).withColumn("value",F.split('col','=')[1]).drop('col')
#%%
tst_pivot = tst_map.groupby(F.lit(1)).pivot('key').agg(F.collect_list(('value'))).drop('1')
#%%
tst_arr = [tst_pivot.select(F.posexplode(coln)).withColumnRenamed('col',coln) for coln in tst_pivot.columns]
tst_fin = reduce(lambda df1,df2:df1.join(df2,on='pos',how='full'),tst_arr).orderBy('pos')
tst_fin.show()
+---+----+----+----+----+
|pos| A| B| C| D|
+---+----+----+----+----+
| 0|id3a|id3b|id1c|id1d|
| 1|id4a|id1b|id2c|null|
| 2|id1a|id2b|id3c|null|
| 3|id2a|null|null|null|
+---+----+----+----+----
可能有更好的方法,但一种方法是在空格上拆分列以创建条目数组,然后使用高阶函数(spark 2.4+)在拆分数组中的每个条目上拆分
'='
。然后分解并创建两列,一列带有id,另一列带有值。然后我们可以为每个分区和组分配一个行号,然后pivot:
import pyspark.sql.functions as F
df1 = (df.withColumn("Col1",F.split(F.col("Col1"),"\s+")).withColumn("Col1",
F.explode(F.expr("transform(Col1,x->split(x,'='))")))
.select(F.col("Col1")[0].alias("cols"),F.col("Col1")[1].alias("vals")))
from pyspark.sql import Window
w = Window.partitionBy("cols").orderBy("cols")
final = (df1.withColumn("Rnum",F.row_number().over(w)).groupBy("Rnum")
.pivot("cols").agg(F.first("vals")).orderBy("Rnum"))
这就是变换后df1的样子:
df1.show()
+----+----+
|cols|vals|
+----+----+
| A|id1a|
| A|id2a|
| B|id1b|
| C|id1c|
| B|id2b|
| D|id1d|
| A|id3a|
| B|id3b|
| C|id2c|
| A|id4a|
| C|id3c|
+----+----+
你能提供一个可复制的数据样本吗?
df1.show()
+----+----+
|cols|vals|
+----+----+
| A|id1a|
| A|id2a|
| B|id1b|
| C|id1c|
| B|id2b|
| D|id1d|
| A|id3a|
| B|id3b|
| C|id2c|
| A|id4a|
| C|id3c|
+----+----+