¿Cómo iterar a través de los valores distintos de una columna en una gran Pyspark trama de datos? .distinct (). collect () lanza una advertencia gran tarea

votos
0

Estoy tratando de iterar a través de todos los valores distintos en la columna de un gran Pyspark trama de datos. Cuando trato de hacerlo utilizando .distinct (). Collect () plantea una tarea demasiado grande, advirtiendo incluso si sólo hay dos valores distintos. Aquí hay un código de ejemplo:

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])+')

Este código produce esta advertencia que se refiere a la línea para x en 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.

¿Cómo se puede iterar a través de los valores distintos en una columna de una gran Pyspark trama de datos sin toparse con problemas de memoria?

Publicado el 13/01/2020 a las 21:54
fuente por usuario
En otros idiomas...                            


2 respuestas

votos
0

Como ya saben, .collect()no es una buena práctica. Porque, es una acción que transferir todos los datos de los ejecutores para el conductor. Así, en una gran trama de datos con una gran cantidad de valores distintos, la colecta no funcionará en absoluto. La raíz de su problema es que usted quiere traer a todos sus datos distribuidos desde los ejecutores de JVM en el PVM conductor.

En un nivel alto, alrededor de trabajo para su problema podría ser a la memoria de intercambio con el disco.

Usted puede escribir su trama de datos con valores distintos en un csv y luego volver a leerlo línea por línea con Python o pandas *:

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

Con esta solución no tendrá ningún problema con la memoria.

* Hay una gran cantidad de soluciones sobre cómo leer una gran CSV con Python o pandas.

Respondida el 14/01/2020 a las 22:37
fuente por usuario

votos
0

La advertencia:

20/01/13 20:39:01 WARN TaskSetManager: Etapa 0 contiene una tarea de gran tamaño (154 KB). El tamaño de la tarea máxima recomendada es de 100 KB.

Se refiere al tamaño de la tarea que la chispa de envío a los ejecutores. Por lo tanto, creo que esto no tiene nada que ver con la memoria, pero con el tamaño de la tarea y los datos se envían con él. En su caso, los datos se produce a través de:

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

Ahora el problema es que el tamaño de trama de datos que excede el tamaño del tamaño tarea permitido que es de 100 KB. Puede recuperar el tamaño de la table_datacon:

table_data.info(memory_usage='deep')

Esto debe darle aproximadamente 4.6MB = 4710.4KB. En su caso, el tamaño de la tarea es 154KB partir de la cual se puede concluir que el conjunto de datos tiene 4710/154 ~ 30 particiones (por favor confirmar si es posible con data.rdd.getNumPartitions()).

La solución podría ser la de reparto a un número más alto con el fin de tener un tamaño más pequeño tarea <= 100KB es decir: 4710/50 = 94.2KB. Su consulta final, debe ser lo siguiente:

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

Lo que ocurre ahora es que nos separamos el conjunto de datos inicial hasta 50 particiones que se traduce en tamaño de los datos mucho más pequeña para cada tarea (~ 94KB como vimos más arriba).

Respondida el 29/01/2020 a las 17:10
fuente por usuario

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