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、私はそれを行うべきか、単一のデータフレームにS」を?

私はすでにを試しましたunionAllが、この関数は2つの引数のみを受け入れます。

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)

3つ以上のデータフレームを行ごとに結合する方法はありますか?

これを行う目的はCrossValidator、PySpark メソッドを使用せずに手動で10倍のクロス検証を実行することです。したがって、9をトレーニングに、1をテストデータに、それから他の組み合わせで繰り返します。


1
これは質問に直接答えるものではありませんが、ここでは、たとえば、次のように入力する必要がないように、命名方法を改善するための提案をします。[td1、td2、td3、td4、td5、td6、td7 、td8、td9、td10]。100倍のCVでこれを行うことを想像してください。以下は私がやることです:部分= [0.1] * 10 cv = df7.randomSplit(portions)folds = list(range(10))for i in range(10):test_data = cv [i] fold_no_i = folds [: i] + folds [i + 1:] train_data = fold_no_i [1:]のjのcv [fold_no_i [0]]:train_data = train_data.union(cv [j])
ngoc thoag

回答:


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の代わりに通常のRDDである場合、それらのリストをSparkContextのunion関数に渡すことができます

編集:あなたの目的のために、別の方法を提案します。クロス検証のためにこの折り畳み全体を10回繰り返す必要があるため、行が属する折り畳みのラベルを追加し、すべての折り畳みに基づいてDataFrameをフィルタリングしますラベル


(+1)良い回避策。ただし、複数のデータフレームの連結を可能にする関数が必要です。かなり便利でしょう!
Dawny33

私はそれに反対しません
Jan van der Vegt

@JanvanderVegtありがたいことに、それは機能し、ラベルを追加してトレーニングデータセットとテストデータセットを除外するというアイデアを既に実現しました。手伝ってくれてありがとうございます。
クリシュナプラサード

@Jan van der Vegt Joinに同じロジックを適用し、この質問に答えてください
GeorgeOfTheRF


6

結合するデータフレームの列の順序が同じでない場合は、両方のdfが結合前に同じ列の順序になるようにdf2.select(df1.columns)を使用することをお勧めします。

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])
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.