การผสานเฟรมข้อมูลหลายแถวใน 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)

มีวิธีการรวมมากกว่าสองเฟรมข้อมูลแถวฉลาด?

วัตถุประสงค์ของการทำเช่นนี้คือฉันกำลังทำการตรวจสอบความถูกต้องไขว้ 10 เท่าด้วยตนเองโดยไม่ต้องใช้CrossValidatorวิธีPySpark ดังนั้นการฝึก 9 ข้อและ 1 ลงในข้อมูลทดสอบจากนั้นฉันจะทำซ้ำสำหรับชุดค่าผสมอื่น ๆ


1
นี่ไม่ได้ตอบคำถามโดยตรง แต่ที่นี่ฉันให้คำแนะนำเพื่อปรับปรุงวิธีการตั้งชื่อดังนั้นในท้ายที่สุดเราไม่ต้องพิมพ์ตัวอย่างเช่น: [td1, td2, td3, td4, td5, td6, td7 , td8, td9, td10] ลองนึกภาพการทำเช่นนี้เพื่อ CV 100 เท่า นี่คือสิ่งที่ฉันจะทำ: ส่วน = [0.1] * 10 cv = df7.randomSplit (ส่วน) folds = รายการ (ช่วง (10)) สำหรับ i ในช่วง (10): test_data = cv [i] fold_no_i = folds [: i] + folds [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 เดียว

หากแทนที่จะเป็น DataFrames จะเป็น RDD ปกติคุณสามารถส่งรายการของพวกเขาไปยังฟังก์ชัน union ของ SparkContext ของคุณ

แก้ไข: เพื่อจุดประสงค์ของคุณฉันเสนอวิธีการที่แตกต่างกันเนื่องจากคุณจะต้องทำซ้ำทั้งหมด 10 ครั้งสำหรับรอยพับที่ต่างกันของคุณสำหรับ crossvalidation ฉันจะเพิ่มป้ายกำกับสำหรับการพับแถวเป็นของและเพียงกรอง DataFrame ของคุณทุกครั้ง ฉลาก


(+1) การทำงานที่ดี อย่างไรก็ตามจำเป็นต้องมีฟังก์ชั่นที่อนุญาตให้มีการต่อเชื่อมหลายดาต้าเฟรม จะค่อนข้างมีประโยชน์!
Dawny33

ฉันไม่เห็นด้วยกับเรื่องนี้
ม.ค. van der Vegt

@JanvanderVegt ขอบคุณมันใช้งานได้และแนวคิดในการเพิ่มป้ายกำกับเพื่อกรองชุดข้อมูลการฝึกอบรมและการทดสอบฉันทำไปแล้ว ขอบคุณมากสำหรับความช่วยเหลือของคุณ.
krishna Prasad

@Jan van der Vegt คุณช่วยกรุณาใช้ตรรกะเดียวกันนี้สำหรับเข้าร่วมและตอบคำถามนี้ได้
ไหม


6

บางครั้งเมื่อ dataframes ที่จะรวมไม่มีคำสั่งของคอลัมน์เดียวกันมันจะดีกว่าหาก 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.