Come si fa a iterare attraverso valori distinti di una colonna in una grande Pyspark dataframe? .distinct (). Collect () solleva un grande avvertimento compito

voti
0

Sto cercando di scorrere tutti i valori distinti nella colonna di un grande Pyspark dataframe. Quando provo a farlo utilizzando .distinct (). Collect () solleva un compito troppo grande Attenzione, anche se ci sono solo due valori distinti. Ecco alcuni esempi di codice:

import pandas as pd
import numpy as np
from pyspark.sql import SparkSession
import pyarrow as pa

spark = SparkSession.builder.appName('Basics').getOrCreate()
spark.conf.set(spark.sql.execution.arrow.enabled, 'true')
length = 200000
table_data = pd.DataFrame({'a': np.random.randint(2,size = length), 'b': np.random.randint(2,size = length),'c': np.random.randint(2,size = length)})

data = spark.createDataFrame(table_data)

for x in data.select(a).distinct().collect():
    data = data.filter(a == '+str(x[0])+')

Questo codice produce l'avviso che si riferisce alla linea for x in data.select ( a ) distinta () collect ()..:

20/01/13 20:39:01 WARN TaskSetManager: Stage 0 contains a task of very large size (154 KB). The maximum recommended task size is 100 KB.

Come è possibile scorrere i valori distinti in una colonna di un grande Pyspark dataframe senza incorrere in problemi di memoria?

È pubblicato 13/01/2020 alle 21:54
fonte dall'utente
In altre lingue...                            


2 risposte

voti
0

Come già sapete, .collect()non è una pratica migliore. Perché, è un'azione che trasferire tutti i dati dal esecutori al conducente. Così, in una grande dataframe con un sacco di valori distinti, la raccolta non funzionerà affatto. Il vostro principale problema è che si desidera portare tutti i dati distribuiti dalle esecutori JVM nel PVM conducente.

In un livello alto, un lavoro in giro per il vostro problema potrebbe essere nella memoria di scambio con il disco.

È possibile scrivere il dataframe con valori distinti in un unico CSV e poi leggerlo di nuovo riga per riga con Python o Pandas *:

data.select("a").distinct().coalesce(1).write.csv("temp.csv")
# Specifically, it's a directory with one csv.

Con questa soluzione non si avrà alcun problema con la memoria.

* Ci sono un sacco di soluzioni su come leggere una grande CSV con Python o Panda.

Risposto il 14/01/2020 a 22:37
fonte dall'utente

voti
0

L'avviso:

20/01/13 20:39:01 WARN TaskSetManager: Stadio 0 contiene un'attività di dimensioni molto grandi (154 KB). La dimensione massima consigliata compito è 100 KB.

Si riferisce alle dimensioni compito che Spark invio di esecutori. Pertanto, credo che questo non ha nulla a che fare con la memoria, ma con la dimensione del compito e i dati inviati con esso. Nel tuo caso il dato è prodotta tramite:

pd.DataFrame({'a': np.random.randint(2,size = length), 'b': np.random.randint(2,size = length),'c': np.random.randint(2,size = length)})

Ora il problema è che la dimensione di tale dataframe supera la dimensione della dimensione compito consentita che è 100KB. È possibile recuperare la dimensione del table_datacon:

table_data.info(memory_usage='deep')

Questo dovrebbe dare circa 4.6MB = 4710.4KB. Nel tuo caso la dimensione del compito è 154KB da cui possiamo concludere che l'insieme di dati ha 4710/154 ~ 30 partizioni (Si prega di confermare se possibile con data.rdd.getNumPartitions()).

La soluzione potrebbe essere quella di ripartizione di un numero superiore per avere una dimensione più piccola compito <= 100KB cioè: 4710/50 = 94.2KB. La query finale dovrebbe essere come prossimo:

data.repartition(50).select("a").distinct().collect()

Quello che è successo ora è che abbiamo diviso il set di dati iniziali a 50 partizioni che si traduce in dimensioni dei dati molto più piccolo per ogni attività (~ 94KB come abbiamo visto sopra).

Risposto il 29/01/2020 a 17:10
fonte dall'utente

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more