在PySpark中逐行合并多个数据帧


21

我有10个数据帧pyspark.sql.dataframe.DataFrame,从获得randomSplit(td1, td2, td3, td4, td5, td6, td7, td8, td9, td10) = td.randomSplit([.1, .1, .1, .1, .1, .1, .1, .1, .1, .1], seed = 100)现在我想参加9 td的到一个单一的数据帧,我应该怎么办呢?

我已经尝试过使用unionAll,但是此函数仅接受两个参数。

td1_2 = td1.unionAll(td2) 
# this is working fine

td1_2_3 = td1.unionAll(td2, td3) 
# error TypeError: unionAll() takes exactly 2 arguments (3 given)

有什么办法可以按行组合两个以上的数据帧?

这样做的目的是在不使用PySpark CrossValidator方法的情况下手动进行10倍交叉验证,因此将9用于训练,将1用于测试数据,然后将其用于其他组合。


1
这不能直接回答问题,但是在这里我提出了一个改进命名方法的建议,以便最终不必键入,例如:[td1,td2,td3,td4,td5,td6,td7 ,td8,td9,td10]。想象一下,这样做是为了获得100倍的简历。这是我要做的:份数= [0.1] * 10 cv = df7.randomSplit(部分)folds = list(range(10))对于range(10)中的i:test_data = cv [i] fold_no_i = folds [: i] + folds [i + 1:] train_data = cv [fold_no_i [0]] for fold_no_i [1:]:train_data = train_data.union(cv [j])
ngoc thoag

Answers:


37

被盗:https//stackoverflow.com/questions/33743978/spark-union-of-multiple-rdds

在链接联合之外,这是对DataFrame执行此操作的唯一方法。

from functools import reduce  # For Python 3.x
from pyspark.sql import DataFrame

def unionAll(*dfs):
    return reduce(DataFrame.unionAll, dfs)

unionAll(td2, td3, td4, td5, td6, td7, td8, td9, td10)

发生的情况是,它将所有传递的对象作为参数,并使用unionAll对其进行还原(此归约方法来自Python,尽管其工作原理类似,但不是Spark归约法),最终将其归为一个DataFrame。

如果不是DataFrames而是正常的RDD,则可以将它们的列表传递给SparkContext的union函数

编辑:出于您的目的,我提出了一种不同的方法,因为对于交叉验证,您将必须对整个折叠重复10次整个联合,因此我将添加一行所属的标签,并根据以下内容对每个折叠过滤DataFrame标签


(+1)一个不错的解决方法。但是,需要有一个允许多个数据帧串联的功能。会很方便!
Dawny33

我不同意
Jan van der Vegt

@JanvanderVegt谢谢,它可以工作,并且添加标签以过滤出训练和测试数据集的想法,我已经做到了。非常感谢您的帮助。
克里希纳·普拉萨德

@Jan van der Vegt您能为Join应用相同的逻辑吗,并回答这个问题
GeorgeOfTheRF


6

有时,当要合并的数据帧的列顺序不同时,最好使用df2.select(df1.columns),以确保两个df在联合前具有相同的列顺序。

import functools 

def unionAll(dfs):
    return functools.reduce(lambda df1,df2: df1.union(df2.select(df1.columns)), dfs) 

例:

df1 = spark.createDataFrame([[1,1],[2,2]],['a','b'])
# different column order. 
df2 = spark.createDataFrame([[3,333],[4,444]],['b','a']) 
df3 = spark.createDataFrame([555,5],[666,6]],['b','a']) 

unioned_df = unionAll([df1, df2, df3])
unioned_df.show() 

在此处输入图片说明

否则它将产生以下结果。

from functools import reduce  # For Python 3.x
from pyspark.sql import DataFrame

def unionAll(*dfs):
    return reduce(DataFrame.unionAll, dfs) 

unionAll(*[df1, df2, df3]).show()

在此处输入图片说明


2

如何使用递归?

def union_all(dfs):
    if len(dfs) > 1:
        return dfs[0].unionAll(union_all(dfs[1:]))
    else:
        return dfs[0]

td = union_all([td1, td2, td3, td4, td5, td6, td7, td8, td9, td10])
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.