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했지만이 함수는 두 개의 인수 만 허용합니다.

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 배 CV에서이 작업을 수행한다고 상상해보십시오. 내가 할 일은 다음과 같습니다 : parts = [0.1] * 10 cv = df7.randomSplit (portions) folds = range (10)의 i에 대한 list (range (10)) : test_data = cv [i] fold_no_i = folds [: i] + 접기 [i + 1 :] train_data = cv [fold_no_i [0]]에서 j의 경우 fold_no_i [1 :]에서 : train_data = train_data.union (cv [j])
ngoc thoag

답변:


37

도난 : /programming/33743978/spark-union-of-multiple-rdds

체이닝 유니언 외부에서는 이것이 DataFrames를위한 유일한 방법입니다.

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으로 줄입니다.

DataFrame 대신 일반 RDD 인 경우 해당 목록을 SparkContext의 공용 함수에 전달할 수 있습니다.

편집 : 목적에 따라 다른 방법을 제안합니다. 교차 유효성 검사를 위해 다른 접기에 대해이 전체 조합을 10 번 반복해야하기 때문에 행이 속한 접기에 레이블을 추가하고 모든 접기에 대해 DataFrame을 필터링합니다. 라벨


(+1) 좋은 해결책입니다. 그러나 여러 데이터 프레임을 연결할 수있는 기능이 필요합니다. 꽤 편리합니다!
Dawny33

나는 그것에 동의하지 않습니다
Jan van der Vegt

@JanvanderVegt 고마워, 그것은 작동하고 훈련 및 테스트 데이터 세트를 필터링하기 위해 레이블을 추가하는 아이디어, 나는 이미 그것을했다. 당신의 도움을 주셔서 대단히 감사합니다.
krishna Prasad

@Jan van der Vegt 동일한 논리를 적용하고이 질문에 답하십시오
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])
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.