Unione di più frame di dati in ordine di riga in PySpark


21

Ho telai 10 di dati pyspark.sql.dataframe.DataFrame, ottenuti da randomSplitcome (td1, td2, td3, td4, td5, td6, td7, td8, td9, td10) = td.randomSplit([.1, .1, .1, .1, .1, .1, .1, .1, .1, .1], seed = 100)Ora voglio unire 9 td's in un singolo frame di dati, come devo fare?

Ho già provato con unionAll, ma questa funzione accetta solo due argomenti.

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)

Esiste un modo per combinare più di due frame di dati per riga?

Lo scopo di questo è che sto facendo manualmente 10 volte Cross Validation senza usare il CrossValidatormetodo PySpark , quindi prendendo 9 in allenamento e 1 in dati di test e poi lo ripeterò per altre combinazioni.


1
Questo non risponde direttamente alla domanda, ma qui do un suggerimento per migliorare il metodo di denominazione in modo che alla fine non dobbiamo digitare, ad esempio: [td1, td2, td3, td4, td5, td6, td7 , td8, td9, td10]. Immagina di farlo per un CV 100 volte. Ecco cosa farò: portions = [0.1] * 10 cv = df7.randomSplit (porzioni) folds = list (range (10)) per i in range (10): test_data = cv [i] fold_no_i = folds [: i] + folds [i + 1:] train_data = cv [fold_no_i [0]] per j in fold_no_i [1:]: train_data = train_data.union (cv [j])
ngoc thoag

Risposte:


37

Rubato da: /programming/33743978/spark-union-of-multiple-rdds

Al di fuori del concatenamento dei sindacati questo è l'unico modo per farlo per 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)

Quello che succede è che prende tutti gli oggetti che hai passato come parametri e li riduce usando unionAll (questa riduzione è da Python, non la riduzione Spark anche se funzionano in modo simile) che alla fine lo riduce a un DataFrame.

Se invece di DataFrames sono normali RDD, puoi passarne un elenco alla funzione di unione di SparkContext

MODIFICA: Per il tuo scopo, propongo un metodo diverso, dal momento che dovresti ripetere questa intera unione 10 volte per le tue diverse pieghe per la convalida incrociata, aggiungerei etichette per cui appartiene una riga e filtrerei il tuo DataFrame per ogni piega in base a l'etichetta


(+1) Una bella soluzione. Tuttavia, deve esistere una funzione che consenta la concatenazione di più frame di dati. Sarebbe abbastanza utile!
Dawny33

Non sono d'accordo
Jan van der Vegt,

@JanvanderVegt Grazie, funziona e l'idea di aggiungere etichette per filtrare il set di dati di training e testing, l'ho già fatto. Grazie mille per il tuo aiuto.
Krishna Prasad,

@Jan van der Vegt Puoi per favore applicare la stessa logica per Join e rispondere a questa domanda
GeorgeOfTheRF


6

A volte, quando i frame di dati da combinare non hanno lo stesso ordine di colonne, è meglio df2.select (df1.columns) per assicurarsi che entrambi i df abbiano lo stesso ordine di colonne prima dell'unione.

import functools 

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

Esempio:

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() 

inserisci qui la descrizione dell'immagine

altrimenti genererebbe invece il risultato seguente.

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()

inserisci qui la descrizione dell'immagine


2

Che ne dici di usare la ricorsione?

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])
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.