Pyspark-将多列数据合并为一个跨行分布的单列

时间:2020-02-06 18:07:28

标签: python apache-spark pyspark

我有一个带有多列的pyspark数据框,如下所示:

name    col1    col2    col3
A        1        6       7
B        2        7       6
C        3        8       5
D        4        9       4
E        5        8       3

我想通过将列名和col1,col2,col3的列名称和列值组合成两个新列(例如new_col和new_col_val)在pyspark中创建一个新的数据框,跨行:

enter image description here

我使用以下代码在R中做了同样的事情:

df1 <- gather(df,new_col,new_col_val,-name)

我想创建3个单独的数据框,这些数据框将包含原始数据框的每一列,然后将它们附加在一起,但是我的数据具有超过2500k行和大约60列。创建多个数据帧将是最糟糕的主意。 谁能告诉我如何在pyspark中做到这一点?

3 个答案:

答案 0 :(得分:5)

您可以使用unionAll将列转换为行,并可以使用lit指定列名,如下所示,

from pyspark.sql.functions import lit

df2 = df.select(df.columns[0], lit(df.columns[1]).alias('new_col'),
                df[df.columns[1]].alias('new_col_val'))

for i in df.columns[2:]:
    df2 = df2.unionAll(df.select(df.columns[0], lit(i), df[i]))

输出:

+----+-------+-----------+
|name|new_col|new_col_val|
+----+-------+-----------+
|   A|   col1|          1|
|   B|   col1|          2|
|   C|   col1|          3|
|   D|   col1|          4|
|   E|   col1|          5|
|   A|   col2|          6|
|   B|   col2|          7|
|   C|   col2|          8|
|   D|   col2|          9|
|   E|   col2|          8|
|   A|   col3|          7|
|   B|   col3|          6|
|   C|   col3|          5|
|   D|   col3|          4|
|   E|   col3|          3|
+----+-------+-----------+

注意:所有列必须具有相同的数据类型。

要检查列是否具有相同的数据类型,

if len(set(map(lambda x: x[-1], df.dtypes[1:]))) != 1:
    raise AssertionError("All columns must be of the same datatype")

答案 1 :(得分:2)

基本上,您正试图取消对列的枢纽操作,并且可以在火花中执行以下操作:

from pyspark.sql.functions import expr
data.select("name",expr("stack(3,'col1',col1,'col2',col2,'col3',col3) as (new_col, new_col_val)")).show()

答案 2 :(得分:0)

使用melt函数相对简单。

sdf = spark.createDataFrame(pdf)
melt(sdf, id_vars=['name'], value_vars=['col1', 'col2', 'col3']).show()