繁体   English   中英

Pyspark-转置多个数据框

[英]Pyspark - Transpose multiple dataframe

我有多个看起来像这样的数据框。

df1:

+---------+---------+---------+
|sum(col1)|sum(col2)|sum(col3)|
+---------+---------+---------+
|       10|        1|        0|
+---------+---------+---------+

df2:

+---------+---------+
|sum(col1)|sum(col2)|
+---------+---------+
|       20|        6|
+---------+---------+

df3:

+---------+---------+---------+---------+
|sum(col1)|sum(col2)|sum(col3)|sum(col4)|
+---------+---------+---------+---------+
|        1|        5|        3|        4|
+---------+---------+---------+---------+

对于上面的示例,输出应如下所示。

+--------+------+------+------+
|col_name|value1|value2|value3|
+--------+------+------+------+
|    col1|    10|    20|     1|
|    col2|     1|     6|     5|
|    col3|     0|  null|     3|
|    col4|  null|  null|     4|
+--------+------+------+------+

我正在使用spark 1.6.3来做到这一点。 在上面的示例中,我对特定表有不同的总和计算,但是我有多个表要为每个表计算总和,输出应以上述格式合并。

关于如何做到这一点的任何想法?

这可能是在pyspark之外最容易执行的操作,并且如果要处理的数据足够小,则可能应该这样做,因为在pyspark上执行此操作将不会特别有效。

如果出于某种原因需要执行此操作,请使用pyspark,可以通过几个数据框转换来执行此操作。 我们需要做的第一件事是将所有单个数据帧转换为相同的架构,这将允许我们迭代地从每个数据帧中进行选择,然后合并为最终结果。 以下是实现此目的的一种方法。

from pyspark.sql.functions import lit,col
from pyspark.sql.types import StructType, StructField, IntegerType, StringType

a = [[10,1,0]]
b = [[20,6]]
c = [[1,5,3,4]]

dfa = spark.createDataFrame(a,['col1','col2','col3'])
dfb = spark.createDataFrame(b,['col1','col2'])
dfc = spark.createDataFrame(c,['col1','col2','col3','col4'])

dfdict = {'dfa':dfa,'dfb':dfb,'dfc':dfc}
columns = set([col for dfname in dfdict for col in dfdict[dfname].columns])

for dfname in dfdict:
    for colname in columns-set(dfdict[dfname].columns):
        dfdict[dfname] = dfdict[dfname].withColumn(colname, lit(None).cast(StringType()))

schema = StructType([StructField("col_name", StringType(), True)]+\
                    [StructField("value_"+dfname, IntegerType(), True) for dfname in dfdict])
resultdf=spark.createDataFrame([],schema = schema)

for colname in columns:
    resultdf = resultdf\
                .union(dfdict['dfa'].select(lit(colname).alias('col_name'),
                       col(colname).alias('value_dfa'))\
                .crossJoin(dfdict['dfb'].select(col(colname).alias('value_dfb')))\
                .crossJoin(dfdict['dfc'].select(col(colname).alias('value_dfc'))))

resultdf.orderBy('col_name').show()

>>>

+--------+---------+---------+---------+
|col_name|value_dfa|value_dfb|value_dfc|
+--------+---------+---------+---------+
|    col1|       10|       20|        1|
|    col2|        1|        6|        5|
|    col3|        0|     null|        3|
|    col4|     null|     null|        4|
+--------+---------+---------+---------+

可能有一些方法可以通过删除交叉连接并将其替换为更聪明的方法来提高其效率。

如果需要处理具有多行的起始数据帧,则需要将行聚合在一起(或更改预期输出的要求)。 例如,您可能希望对所有内容进行汇总,例如以下示例。

from pyspark.sql.functions import sum

d = [[1,2,3],[4,5,6]]
dfd = spark.createDataFrame(a,['col1','col2','col3'])

dfdagg = dfd.groupby().agg(*[sum(col) for colname in dfa.columns])

现在可以以与上面使用其他数据帧相同的方式使用dfdagg

另一种方法是,您可以使用堆栈函数转置dfs,然后将它们合并

>>> df1x = df1.selectExpr("stack(3, 'col1', col1, 'col2', col2, 'col3', col3) as (col_name, value1)")
>>> df1x.show()
+--------+------+
|col_name|value1|
+--------+------+
|    col1|    10|
|    col2|     1|
|    col3|     0|
+--------+------+

>>> df2x = df2.selectExpr("stack(2, 'col1', col1, 'col2', col2) as (col_name, value2)")
>>> df2x.show()
+--------+------+
|col_name|value2|
+--------+------+
|    col1|    20|
|    col2|     6|
+--------+------+

>>> df3x = df3.selectExpr("stack(4, 'col1', col1, 'col2', col2, 'col3', col3, 'col4', col4) as (col_name, value3)")
>>> df3x.show()
+--------+------+
|col_name|value3|
+--------+------+
|    col1|     1|
|    col2|     5|
|    col3|     3|
|    col4|     4|
+--------+------+

>>> df1x.join(df2x, "col_name", "full").join(df3x, "col_name", "full").sort("col_name").show()
+--------+------+------+------+                                                 
|col_name|value1|value2|value3|
+--------+------+------+------+
|    col1|    10|    20|     1|
|    col2|     1|     6|     5|
|    col3|     0|  null|     3|
|    col4|  null|  null|     4|
+--------+------+------+------+

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM